1. 程式人生 > >實現你的第一個連結串列——手把手教你建立單向連結串列

實現你的第一個連結串列——手把手教你建立單向連結串列

寫在前面

這是我原發在獨立部落格上的文章,用來幫助初學連結串列的同學們理解連結串列,現在發在這裡供大家批評。

為什麼要使用連結串列?

這是我們首先要考慮的一個問題,我們之前已經學過了陣列的使用,可以方便快速地儲存大量資料,為何還要引入“連結串列”的概念呢?

比如我們讓50個小朋友排排坐,那事情是很好辦的:只需要準備50個椅子,讓小朋友們依次坐好即可,這就是陣列的使用。但是,如果我們預先不知道有多少小朋友,那事情就不好辦了,我們可能需要準備大量的椅子,但這就會浪費很多空間;此外,如果一個新來的小朋友必須進入特定兩人之間,椅子是靜態的,只能讓後面的人一個一個依次往後挪,他才能坐到這個位置,這無疑十分浪費時間。

因此,在這種情況下,我們不再讓小朋友排排坐,而是讓每人拉著另一個人的衣襟,這樣不需要確定椅子數,如果有人需要插入,也只需改變一兩個人拉誰的衣襟即可。這也就是我們所說的連結串列。(要注意,這裡是“拉衣襟”而不是“手拉手”,因此嚴格地說是一種單向連結串列)

C語言實現

實現方式的選擇

我們現在已經知道,要實現連結串列,我們需要有資料(小朋友),又要把資料連起來(拉衣襟),在程式設計中,我們特別需要考慮對“拉衣襟”的實現,這時,C語言中的指標就為我們提供了絕佳的工具,因為它可以指向其他的元素。為了將資料和指標組合起來,我們需要一個結構體,在連結串列中,我們將這種資料域指標域的組合稱為結點

(node)。

在這裡的例子中,為了簡單,我們在每個結點只儲存一個整型變數:

typedef struct linked_list {
    int num;
    struct linked_list* next;
} l;

在這個結點中,資料域為整型變數num,指標域為指標next,用來指向下一個結點,結點之間依次相連,從而實現“拉衣襟”的操作。

建立結點

建立頭結點

很多時候,我們都需要先建立一個不儲存資料的頭結點,這樣即使遇到空連結串列或對第一個元素的操作等情況也不會出現問題。(注:在課本示例中,並沒有使用頭結點,但我認為最好使用)

特別注意下面幾個名詞的區別!

  • 頭結點:一個空結點,位於單向連結串列最前面,它的指標域指向第一個有資料的結點
  • 尾結點:最後一個結點,它的指標域最終指向NULL
  • 頭指標:指向頭結點的指標,在訪問單向連結串列時要從這個指標所指的結點開始
  • 尾指標:指向尾結點的指標,用於建立連結串列過程中的操作
l * head, * new_node, * tail; //宣告頭指標、建立新結點所用指標、尾指標
head = (l*)malloc(sizeof(l)); //為頭結點分配記憶體
tail = head; //讓尾指標指向頭指標

建立資料結點

接下來我們就可以建立有資料的結點內容了!下面先以其中一個結點為例:

new_node = (l*)malloc(sizeof(l)); //為結點分配記憶體
scanf("%d", &new_node->num); //輸入資料
tail->next = new_node; //讓尾結點的指標域指向新建立的結點
tail = new_node; //讓尾指標指向新的結點

當然,在實際中,肯定不會只建立一個數據結點,而是用迴圈語句建立完所需的所有結點。

結束連結串列建立

現在,我們假設所有結點建立完畢,需要進行最後一步——將尾結點的指標域指向NULL,這樣就可以標記連結串列的結束。

tail->next = NULL;

建立連結串列的整體操作

#include<cstdio>
#include<cstdlib>

//使用結構體構建結點
typedef struct linked_list {
    int num;
    struct linked_list* next;
} l;

l* create(int n) {
    l * head, * new_node, * tail;
    int i = 0;
    //建立頭結點
    head = (l*)malloc(sizeof(l));
    tail = head;
    //使用迴圈,建立n個數據結點
    for(i=0; i<n; ++i) {
        new_node = (l*)malloc(sizeof(l));
        scanf("%d", &new_node->num);
        tail->next = new_node;
        tail = new_node;
    }
    //將尾結點的指標域指向NULL,標誌連結串列結束
    tail->next = NULL;
    //返回頭指標
    return head;
}

int main() {
    l* head_pointer;
    int n;
    printf("請輸入資料個數:");
    scanf("%d", &n);
    printf("請依次輸入資料:");
    head_pointer = create(n);
    /*
    下面可以進行連結串列操作,本文暫不演示
    */
    return 0;
}

要注意,我們需要在最後讓函式返回頭指標,以便在主函式中通過頭指標訪問我們所建立的連結串列。

總結

本文一步步介紹了建立一個連結串列的方法,由於我寫了半天,現在有點犯懶了,欲知連結串列的訪問、修改等操作,且聽下回分解……