數據結構之鏈表分析與實現

鏈表由多個數據節點組成,每個數據節點由數據域和指針域兩部分組成,如下圖

 其中數據域的類型取決於節點數據類型,若節點爲字符,則數據域類型爲字符型。指針域類型爲地址,存儲着其他節點的內存地址,在C/C++中表現爲節點類型的指針。

計算機存儲鏈表的過程中以數據節點爲基本單位,每個節點都是不可再分的,每次只申請一個節點大小的內存空間,不同節點之間通過指針域連接。這意味着如果在原鏈表上增加和刪除節點十分方便,不必移動其他數據,只需要更改相應的指針域中的內存地址就好,但是當我們訪問鏈表時將會變得十分不方便,只能通過一個又一個節點的指針域不斷跳轉。

常見鏈表分爲單鏈表和雙鏈表,區別在於指針域中指針的個數。單鏈表節點的指針域中只有一個指向下一個節點的指針,指針域爲空時代表該節點爲最後一個節點。這就意味着如果是一個單鏈表,當我們訪問的時候,就只能“一條路走到黑”,沒有其他標記的時候就沒有辦法返回到上一個節點。爲了彌補單鏈表的這種缺陷,我們可以設計雙鏈表,雙鏈表的指針域中不僅有指向下一個節點的指針,還有一個指向上一個節點的指針。

鏈表的增加與刪除,以單鏈表爲例。假設某單鏈表有三個節點a、 b、 c如下,它們的內存地址分別是0x10、0x20、0x30

如果我們要刪除節點b,只需要修改a節點的指針域地址爲c節點的所在地址(0x30),釋放b節點的內存資源即可。

       增加節點則恰恰相反,加入我們需要在a、c兩節點之間在添加一個節點時,只需要申請一個節點b的內存,設置b節點的指針域爲c的節點的地址,然後把a節點的指針域修改爲b節點的地址。一般情況下我們的需求可能是把b節點添加到a節點後面,是沒有c節點的,一定要先將b的指針域設置爲a的指針域的值,然後在設置a的指針域,否則我們將無法找到原本a節點後面的節點

節點的查詢,修改過程不再贅述。

下面是單鏈表的C++簡單實現。

定義節點數據

#define dataType int    //節點數據類型

typedef struct Node {
    dataType data;  //數據域
    struct Node *next;  //指針域
} *list;

插值函數,後插法可以改進非遞歸實現,非遞歸實現的時候需要注意因爲參數L是引用,不要更頭部節點L以及判斷L是否爲空

void insert(list &L, dataType value) {  //鏈表插值函數,L爲鏈表,value爲插入的值
    //以下爲前插法,即每次添加的節點都位於鏈表的第一個
    list p = L;
    L = (list) malloc(sizeof(list));
    L->data = value;
    L->next = p;
    //以下爲後插法,每次插入的節點位於鏈表結尾
    // if(L == NULL) {
    //     L = (list)malloc(sizeof(list));
    //     L->data = value;
    //     L->next = NULL;
    //     return;
    // }
    // else {
    //     insert(L->next, value);
    // }
}

從鏈表中刪除指定值,因爲傳參的過程中L是引用,所以刪除節點後鏈表的結構不會被破壞。

void deleteByValue(list &L, dataType value) {   //刪除指定值的節點,L爲鏈表,value爲匹配值
    if(L == NULL) {
        return;
    }
    if(L->data == value) {  //當前節點需要刪除
        list p = L;
        L = L->next;
        free(p);
        deleteByValue(L, value);
    }
    else {  //當前節點無需刪除
        deleteByValue(L->next, value);
    }
}

鏈表的打印以及銷燬

void printList(list L) {   //打印鏈表
    if(L == NULL) {
        return;
    }
    cout << L->data;
    for (L = L->next; L != NULL; L = L->next) {
        cout << "--->" << L->data;
    }
    cout << endl;
}

void destoryList(list &L) { //銷燬鏈表
    list p;
    while(L != NULL) {
        p = L;
        L = L->next;
        free(p);
    }
}

文件下載

單鏈表.cpp

雙鏈表.cpp

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章