4-雙連結串列的操作

成强發表於2024-07-08

1.定義一個雙連結串列

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int ElemType;

/* 定義一個單連結串列 */
typedef struct DNode {
    /*資料域*/
    ElemType data;
    /*前驅指標域*/
    struct LNode *prior;
    /*後驅指標域*/
    struct LNode *next;
} DNode, *DinkList; /*DNode處理單個節點 ; DinkList處理整個雙連結串列*/


int main() {

    return 0;
}

插入和刪除雙連結串列

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int ElemType;

/* 定義一個雙連結串列節點 */
typedef struct DNode {
    ElemType data;            /* 資料域 */
    struct DNode *prior;      /* 前驅指標域 */
    struct DNode *next;       /* 後驅指標域 */
} DNode, *DLinkList;

/* 初始化雙連結串列 */
DLinkList initDLinkList() {
    DLinkList L = (DLinkList ) malloc(sizeof(DNode));
    if (L == NULL) {
        printf("記憶體分配失敗\n");
        exit(1);
    }
    L->next = NULL;
    L->prior = NULL;
    return L;
}

/* 獲取雙連結串列長度 */
int length(DLinkList L) {
    int len = 0;
    DNode *p = L->next; // 假設L是一個頭節點
    while (p != NULL) {
        len++;
        p = p->next;
    }
    return len;
}

/* 按位查詢,返回第i個位置的節點指標 */
DNode* getElemByPos(DLinkList L, int i) {
    int j = 0;
    DNode *p = L;
    while (p != NULL && j < i) {
        p = p->next;
        j++;
    }
    return p;
}

/* 在雙連結串列的第i個位置插入元素值為x的節點 */
void insertNode(DLinkList L, int i, ElemType x) {
    if (i < 1 || i > length(L) + 1) {
        printf("無效的位置\n");
        return;
    }
    DNode *p = getElemByPos(L, i - 1);
    /*定義一個要插入的節點指標*/
    DNode *s = (DNode *) malloc(sizeof(DNode));
    if (s == NULL) {
        printf("記憶體分配失敗\n");
        exit(1);
    }
    /*修改s地址上的實際 的值*/
    s->data = x;
    /**/
    s->next = p->next;
    if (p->next != NULL) {
        /*當我們插入新節點 s 後,需要確保新節點 s 成為原來第 i 個節點的前驅節點,因此我們將 p->next->prior 設定為 s。
        更詳細的解釋:
        新節點 s 將插入到 p 之後,成為新的第 i 個節點。
        原來的第 i 個節點的前驅節點將更新為新節點 s。*/
        p->next->prior = s;
        /*p->next->prior = s;可以改寫為:如下程式碼*/
        //先獲取原來i位置上的地址指標 (p->next)
        // 原來i位置上的地址指標  變為了 i+1 的位置
        /*所有  原來i位置上的地址指標的前驅指標域prior 變成了新插入的指標s 的地址*/
        //(p->next)->prior=s;
    }
    s->prior = p;
    p->next = s;
}

/* 刪除雙連結串列中第i個位置的節點 */
bool deleteNode(DLinkList L, int i, ElemType *e) {
    if (i < 1 || i > length(L)) {
        return false;
    }
    /*獲取 i-1 位序上的節點地址 */
    DNode *p = getElemByPos(L, i - 1);
    /*獲取要刪除的節點的地址*/
    DNode *q = p->next;
    if (q == NULL) {
        return false;
    }
    /*更新 i-1 的後驅指標域 為 i+1的地址指標*/
    p->next = q->next;
    if (q->next != NULL) {
        q->next->prior = p;
    }
    *e = q->data;
    /*刪除q指標*/
    free(q);
    return true;
}

int main() {
    /* 初始化雙連結串列L為一個帶頭節點的空連結串列 */
    DLinkList L = initDLinkList();

    /* 插入測試資料 */
    insertNode(L, 1, 10); // 在第1個位置插入10
    insertNode(L, 2, 20); // 在第2個位置插入20
    insertNode(L, 1, 5);  // 在第1個位置插入5

    /* 列印連結串列 */
    DNode *p = L->next;
    while (p != NULL) {
        printf("%d -> ", p->data);
        p = p->next;
    }
    printf("NULL\n");

    /* 刪除節點測試 */
    ElemType e;
    if (deleteNode(L, 2, &e)) {
        printf("已刪除節點的值: %d\n", e);
    } else {
        printf("刪除失敗\n");
    }

    /* 再次列印連結串列 */
    p = L->next;
    while (p != NULL) {
        printf("%d -> ", p->data);
        p = p->next;
    }
    printf("NULL\n");

    /* 釋放連結串列 */
    p = L;
    while (p != NULL) {
        DNode *temp = p;
        p = p->next;
        free(temp);
    }

    return 0;
}

相關文章