朱有鵬C語言高階---4.9.12--雙鏈表--刪除節點(雙鏈表的完整程式)(12)
阿新 • • 發佈:2018-10-31
朱有鵬C語言高階---4.9.12--雙鏈表--刪除節點(12)
刪除的過程就是一個遍歷的過程。
刪除尾節點
刪除普通節點
程式碼如下:
#include <stdio.h> #include <stdlib.h> //雙鏈表的節點 struct node { int data; //有效資料 struct node *pPrev; //前向指標,指向前一個節點 struct node *pNext; //後向指標,指向後一個節點 }; struct node *create_node(int data) { struct node *p = (struct node *)malloc(sizeof(struct node)); if (NULL == p) { printf("malloc error.\n"); return NULL; } p->data = data; p->pPrev = NULL; p->pNext = NULL; //預設建立的節點前向和後向指標都指向NULL return p; } // 將新節點new插入到連結串列pH的尾部 void insert_tail(struct node *pH, struct node *new) { // 第一步:先走到連結串列的尾節點 struct node *p = pH; while (NULL != p->pNext) { p = p->pNext; // 第一次迴圈,走過了頭節點 } // 迴圈結束後,p就指向了原來的最後一個節點 // 第二部:將新節點插入到原來的尾節點的後面 p->pNext = new; //後向指標關聯好了,新節點的地址和前節點的next new->pPrev = p; //前向指標關聯好了,新結點的prev和前節點的地址 //前節點的的prev和新節點的next指標未變動 } // 將新節點new前插入連結串列pH中 // 演算法參照圖示進行連結,一共有4個指標需要賦值。注意是順序。 void insert_head(struct node *pH, struct node *new) { // 新節點的next指標指向原來的第一個有效節點的地址 new->pNext = pH->pNext; // 原來第1個有效節點的prev指標指向新節點的地址 if (NULL != pH->pNext)//如果沒有有效節點 pH->pNext->pPrev = new; // 頭節點的next指標指向新節點地址 pH->pNext = new; // 新節點的prev指標指向頭節點的地址 new->pPrev = pH; } // 後向遍歷一個雙鏈表 void bianli(struct node *pH) { struct node *p = pH; if (NULL == p) { return; } while (NULL != p->pNext) { p = p->pNext; printf("data = %d.\n", p->data); } } // 前向遍歷一個雙鏈表,引數pTail要指向連結串列末尾 void qianxiang_bianli(struct node *pTail) { struct node *p = pTail;//當前的p是最後一個節點 while (NULL != p->pPrev) { printf("data = %d.\n", p->data); p = p->pPrev; } } // 從連結串列pH中刪除一個節點,節點的資料是data int delete_node(struct node *pH, int data) { struct node *p = pH; if (NULL == p) { return -1; } while (NULL != p->pNext) { p = p->pNext; //這裡先判斷當前節點是不是我們要刪除的那個節點 if (p->data == data) { //找到了,刪除之。當前的上下文是:當前節點為p if (NULL == p->pNext) { // 尾節點 // p表示當前節點地址,p->pNext表示一個節點地址,p->pPrev表示前一個節點的地址 p->pPrev->pNext = NULL; // p->pPrev = NULL; //可以省略,因為後面整個都被銷燬了 // 銷燬p節點 //free(p); } else { // 不是尾節點,普通節點 // 前一個節點的next指標 指向 後一個節點的收地址 p->pPrev->pNext = p->pNext; // 當前節點的prev和next指標都不用管,因為後面會整體銷燬整個節點 // 後一個節點的prev指標指向前一個節點的首地址 p->pNext->pPrev = p->pPrev; //free(p); } free(p); return 0; } } printf("未找到目標節點.\n"); } int main(void) { struct node *pHeader = create_node(0); //頭指標指向頭節點 //struct node *pHeader = NULL; insert_head(pHeader, create_node(11)); insert_head(pHeader, create_node(12)); insert_head(pHeader, create_node(13)); /* // 遍歷 printf("node 1 data: %d.\n", pHeader->pNext->data); printf("node 2 data: %d.\n", pHeader->pNext->pNext->data); printf("node 3 data: %d.\n", pHeader->pNext->pNext->pNext->data); struct node *p = pHeader->pNext->pNext->pNext; //p指向了最後一個節點 printf("node 3 data: %d.\n", p->data); printf("node 2 data: %d.\n", p->pPrev->data); printf("node 1 data: %d.\n", p->pPrev->pPrev->data); */ //bianli(pHeader); //struct node *p = pHeader->pNext->pNext->pNext; //p指向了最後一個節點 //qianxiang_bianli(p); bianli(pHeader); delete_node(pHeader, 11); printf("after delete node------------\n"); bianli(pHeader); return 0; }