日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

带哨兵节点的链_关于链表中哨兵结点问题的深入剖析

發布時間:2023/12/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 带哨兵节点的链_关于链表中哨兵结点问题的深入剖析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

算法

數據結構

關于鏈表中哨兵結點問題的深入剖析

最近正在學習UC Berkeley的CS61B這門課,主要是采用Java語言去實現一些數據結構以及運用數據結構去做一些project。這門課不僅告訴你這個東西怎么做,而且一步一步探尋為什么要這樣做以及為什么會有這些功能。我們有時在接觸某段代碼或功能的實現時,可能直接就看到了它最終的面貌,而不知道如何一步步演化而來,其實每一個功能的添加或優化都是對應一個問題的解決。下面就這門課中關于鏈表中哨兵結點的相關問題進行總結。

什么是哨兵結點

哨兵顧名思義有巡邏、檢查的功能,在我們程序中通過增加哨兵結點往往能夠簡化邊界條件,從而防止對特殊條件的判斷,使代碼更為簡便優雅,在鏈表中應用最為典型。

單鏈表中的哨兵結點

首先討論哨兵結點在單鏈表中的運用,如果不加哨兵結點在進行頭尾刪除和插入時需要進行特殊判斷。比如在尾部插入結點的代碼如下:

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);

}

如上所示需要對結點為空的特殊情況進行判斷,頭部加了一個哨兵結點后就可以不需要判斷了(不會為空)

雙鏈表中的哨兵結點

Version 1: 雙哨兵

在雙鏈表中需要能夠在頭部和尾部分別進行插入刪除操作(可以實現雙端隊列),為了能快速在尾部進行插入刪除,需要引入指向尾部的指針。截圖如下(圖片來自CS61B)

上述增加了一個指向尾部的last結點,從上圖可以看出一個問題,last結點有時指向哨兵結點,有時指向實際結點。這會導致特殊情況的出現,比如在進行addFirst操作時,last指向哨兵結點時插入后需要將last往后移動一個,而第二張圖指向實際結點時在頭部插入結點后并不需要改變last指針。這時需要在尾部后也引入一個哨兵結點,以使其一致。相應示意圖如下:

Version 2:循環雙鏈表

上述Version1需要兩個哨兵結點,可以對其進行改進。可以使用頭部結點的prev指針指向尾部,尾部結點的next指針指向哨兵,這樣就只需要一個哨兵結點,使鏈表變成循環鏈表,比Version1更為簡潔優雅。

在對如上所示進行插入和刪除操作時一定要格外注意,自己在寫的時候很容易就漏掉某個指針的關系設置,最好在紙上自己畫一遍。(對于要改變的連接可能會影響其他的,這時可將其暫存或最好設置)

在頭部插入的代碼如下:

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;

}

總結與感想

(1)雖然看起來很小很簡單的事情,但實現起來卻有很多細小問題可以考慮,學會把一件小事做的很漂亮。(small but smart)

(2)學會分析一個東西的來龍去脈,為什么會有這部分,以及怎么改進的。

參考:

2.算法導論10.2鏈表

內容來源于網絡,如有侵權請聯系客服刪除

總結

以上是生活随笔為你收集整理的带哨兵节点的链_关于链表中哨兵结点问题的深入剖析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。