1. 程式人生 > >7、鏈表(下):如何輕松寫出正確的鏈表代碼?

7、鏈表(下):如何輕松寫出正確的鏈表代碼?

head 邊界條件 所有 倒數第n個結點 程序 執行 例子 操作 刪除

很汗顏,現在讓自己完整的寫出一個簡單的鏈表結構竟然會無法動筆,作為一個程序猿,需要修行的路還很長。

技巧一:理解指針或引用的含義

將某個變量賦值給指針,實際上就是將這個變量的地址賦值給指針,或者反過來說,指針中存儲了這個變量的內存地址,指向了這個變量,通過指針就能找到這個變量。

例子: p->next = q。這行代碼的意思是p節點的next指針存儲了q節點的內存地址。

同理, p->next = p->next->next。這行代碼的意思是p節點的next指針存儲了p節點的下下一個節點的地址。

技巧二:警惕指針丟失和內存泄漏

舉例插入節點:

技術分享圖片

如圖所示,我們希望在節點a和b之間插入節點x,假設當前指針p指向節點a。如果代碼如下就會發生指針丟失和內存泄漏。

p->next = x;
x->next = p->next; 

此處在p->next執行之後,其指針就不再指向b了,而是指向x。第二行代碼就相當於自己指向了自己。因此,鏈表斷成了兩半,從節點b往後的所有界定啊都無法訪問。

正確方式:將第一行代碼和第二行代碼顛倒順序,就ok了。

技巧三:利用哨兵簡化實現難度

如下,節點p之後插入節點的正確代碼。

x->next = p->next;
p->next = x;

註意:當需要向一個空鏈表中插入第一個節點,上面的邏輯就不能用了。正確答案如下:

if(head==null){
    head = new_node;
}

同理,在編寫鏈表的刪除操作之時,分為兩種情況:

第一種,刪除節點不是尾節點,而是p節點的後繼結點

p->next = p->next->next;

第二種,刪除結點是尾結點

if(node->next == null){
   head = null;  
}

技巧四:重點留意邊界條件處理

如果鏈表為空,代碼能否正常工作?

如果鏈表只包含一個結點時,代碼是否能正常工作?

如果鏈表只包含兩個結點時,代碼是否能正常工作?

代碼邏輯在處理頭結點和尾節點的時候,是否能正常工作?

技巧五:自己畫圖,輔助記憶

常見的鏈表操作:

一、單鏈表反轉

二、鏈表中環的檢測

三、兩個有序的鏈表的合並

四、刪除鏈表倒數第n個結點

五、求鏈表的中間結點

分別對應LeetCode練習題編號:206,141,21,19,876。

課後思考:你是否能想到其他場景,利用哨兵可以大大簡化編碼難度?

後續把自己實現的五種鏈表操作傳上來。歡迎指正!

7、鏈表(下):如何輕松寫出正確的鏈表代碼?