带哨兵节点的链_关于链表中哨兵结点问题的深入剖析
算法
數(shù)據(jù)結(jié)構(gòu)
關(guān)于鏈表中哨兵結(jié)點問題的深入剖析
最近正在學習UC Berkeley的CS61B這門課,主要是采用Java語言去實現(xiàn)一些數(shù)據(jù)結(jié)構(gòu)以及運用數(shù)據(jù)結(jié)構(gòu)去做一些project。這門課不僅告訴你這個東西怎么做,而且一步一步探尋為什么要這樣做以及為什么會有這些功能。我們有時在接觸某段代碼或功能的實現(xiàn)時,可能直接就看到了它最終的面貌,而不知道如何一步步演化而來,其實每一個功能的添加或優(yōu)化都是對應一個問題的解決。下面就這門課中關(guān)于鏈表中哨兵結(jié)點的相關(guān)問題進行總結(jié)。
什么是哨兵結(jié)點
哨兵顧名思義有巡邏、檢查的功能,在我們程序中通過增加哨兵結(jié)點往往能夠簡化邊界條件,從而防止對特殊條件的判斷,使代碼更為簡便優(yōu)雅,在鏈表中應用最為典型。
單鏈表中的哨兵結(jié)點
首先討論哨兵結(jié)點在單鏈表中的運用,如果不加哨兵結(jié)點在進行頭尾刪除和插入時需要進行特殊判斷。比如在尾部插入結(jié)點的代碼如下:
void addLast(int x) {
if (first == null) {
first = new Node(x, null);
return;
}
Node p = first;
while (p.next != null) {
p = p.next;
}
p.next = new Node(x, null);
}
如上所示需要對結(jié)點為空的特殊情況進行判斷,頭部加了一個哨兵結(jié)點后就可以不需要判斷了(不會為空)
雙鏈表中的哨兵結(jié)點
Version 1: 雙哨兵
在雙鏈表中需要能夠在頭部和尾部分別進行插入刪除操作(可以實現(xiàn)雙端隊列),為了能快速在尾部進行插入刪除,需要引入指向尾部的指針。截圖如下(圖片來自CS61B)
上述增加了一個指向尾部的last結(jié)點,從上圖可以看出一個問題,last結(jié)點有時指向哨兵結(jié)點,有時指向?qū)嶋H結(jié)點。這會導致特殊情況的出現(xiàn),比如在進行addFirst操作時,last指向哨兵結(jié)點時插入后需要將last往后移動一個,而第二張圖指向?qū)嶋H結(jié)點時在頭部插入結(jié)點后并不需要改變last指針。這時需要在尾部后也引入一個哨兵結(jié)點,以使其一致。相應示意圖如下:
Version 2:循環(huán)雙鏈表
上述Version1需要兩個哨兵結(jié)點,可以對其進行改進。可以使用頭部結(jié)點的prev指針指向尾部,尾部結(jié)點的next指針指向哨兵,這樣就只需要一個哨兵結(jié)點,使鏈表變成循環(huán)鏈表,比Version1更為簡潔優(yōu)雅。
在對如上所示進行插入和刪除操作時一定要格外注意,自己在寫的時候很容易就漏掉某個指針的關(guān)系設(shè)置,最好在紙上自己畫一遍。(對于要改變的連接可能會影響其他的,這時可將其暫存或最好設(shè)置)
在頭部插入的代碼如下:
public void addFirst(Item item) {
Node node = new Node(item);
node.prev = sentinel;
node.next = sentinel.next;
sentinel.next.prev = node;
sentinel.next = node;
size++;
}
尾部插入代碼如下:
public void addLast(Item item) {
Node node = new Node(item);
node.prev = sentinel.prev;
node.next = sentinel;
sentinel.prev.next = node;
sentinel.prev = node;
size++;
}
頭部刪除代碼如下:
public Item removeFirst() {
Item item = sentinel.next.item;
sentinel.next = sentinel.next.next;
sentinel.next.prev = sentinel;
size--;
return item;
}
尾部刪除代碼如下
public Item removeLast() {
Item item = sentinel.prev.item;
Node sl = sentinel.prev.prev;
sl.next = sl.next.next;
sl.next.prev = sl;
size--;
return item;
}
總結(jié)與感想
(1)雖然看起來很小很簡單的事情,但實現(xiàn)起來卻有很多細小問題可以考慮,學會把一件小事做的很漂亮。(small but smart)
(2)學會分析一個東西的來龍去脈,為什么會有這部分,以及怎么改進的。
參考:
2.算法導論10.2鏈表
內(nèi)容來源于網(wǎng)絡,如有侵權(quán)請聯(lián)系客服刪除
總結(jié)
以上是生活随笔為你收集整理的带哨兵节点的链_关于链表中哨兵结点问题的深入剖析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 消息称腾讯 XR 团队全线解散,官方回应
- 下一篇: mapreduce分组统计_Mongod