線性表——雙向連結串列
阿新 • • 發佈:2018-12-11
雙向連結串列簡介
雙向連結串列是一種特殊的連結串列。
在單向連結串列中我們要查詢下一個結點非常的方便,但是要查詢上一個節點就困難了,雙向連結串列克服了單鏈表的單向性這個缺點,
單鏈表和雙向連結串列的區別
單鏈表:只能向一個方向遍歷
雙向連結串列:向兩邊都可以遍歷。
雙向連結串列的實現
為了找到節點和前驅,我們給節點增加一個指向其前驅的指標,如下圖所示
既然單鏈表可以迴圈,那麼雙向連結串列也就可以迴圈,如下圖所示即為雙向迴圈連結串列
雙向連結串列的基本操作
1.建立雙向連結串列
建立雙向連結串列和建立單鏈表大同小異,雙向連結串列的結點有三個域,資料域、前驅和後繼。
當連結串列為空時,頭結點的前驅和後繼都指向它自己,自己構成一個環。
當連結串列不為空時,除尾結點外,每個結點的前驅都指向它的前一個結點,後繼均指向它的後一個結點,尾節點的後繼指向頭結點。
2.增加元素
把元素增加在連結串列最後。
① 建立一個新的節點
② 新結點的後繼為頭結點
③ 新結點的前驅為尾節點
④ 尾節點的後繼為新結點
⑤ 頭結點的前驅為新結點
⑥ 將尾指標移動到新結點上
把元素插在連結串列任意位置,如下圖所示
① 建立新結點
② 遍歷連結串列到達指定的位置 p
③ 新結點的後繼等於 p 的後繼
④ 新結點的後繼(P的後繼)的前驅等於新結點
⑤ 新結點的前驅等於 p
⑥ p 的後繼等於新結點
3.刪除元素
刪除尾結點
① 尾節點的前驅的後繼等於頭結點
② 頭結點的前驅等於尾節點的前驅
③ 尾指標向前移動一下
刪除任意位置的元素
① 遍歷連結串列到適當的位置 p (待刪除的節點)
② p 的前驅的後繼等於 p 的後繼
③ p 的後繼的前驅等於 p 的前驅
/** * 結點類 */ class Node2<T>{ /** * 資料域 */ T data ; /** * 前驅 */ Node2<T> pre ; /** * 後繼 */ Node2<T> next ; public Node2(){ this.data = null; this.pre = null; this.next = null; } public Node2(T data){ this.data = data; this.pre = null; this.next = null; } } /** * 連結串列 */ class doubleCycle<T>{ /** * 頭結點 */ Node2<T> head; /** * 尾指標 */ Node2<T> last; /** * 雙向迴圈連結串列的長度 */ int size; public doubleCycle(){ head = new Node2<T>(); last = head; head.next = head; head.pre = head; size = 0; } /** * 增加一個元素 * @param data */ public void add(T data){ Node2<T> node = new Node2<T>(data); last.next = node; node.pre = last; node.next = head; head.pre = node; last = node; size++; } /** * 刪除一個元素 * @param data * @return */ public boolean delete(T data){ Node2<T> p = head.next; while(p != head){ if(p.data == data){ if(p == last){//如果是最後一個元素被刪除,則要移動尾指標。 last = p.pre; } p.next.pre = p.pre; p.pre.next = p.next; size--; return true; } p = p.next; } return false; } public void show(){ Node2<T> p = head.next; while(p != head){ System.out.print(p.data+" "); p = p.next; } System.out.println(); } public void show2(){ Node2<T> p = last; while(p != head){ System.out.print(p.data+" "); p = p.pre; } System.out.println(); } } public class demo5 { public static void main(String[] args){ doubleCycle<Integer> link = new doubleCycle<Integer>(); link.add(84); link.add(45); link.add(75); link.add(15); link.add(11); link.add(23); link.add(29); link.add(7); link.show(); link.show2(); link.delete(45); System.out.println("刪除45"); link.show(); link.show2(); link.delete(11); System.out.println("刪除11"); link.show(); link.show2(); link.delete(7); System.out.println("刪除7"); link.show(); link.show2(); } }
執行結果
84 45 75 15 11 23 29 7
7 29 23 11 15 75 45 84
刪除45
84 75 15 11 23 29 7
7 29 23 11 15 75 84
刪除11
84 75 15 23 29 7
7 29 23 15 75 84
刪除7
84 75 15 23 29
29 23 15 75 84