1. 程式人生 > 其它 >4.雙向連結串列

4.雙向連結串列

單鏈表的缺點分析:

  • 單向連結串列,查詢的方向只能是一個方向,而雙向連結串列可以向前或者向後查詢;
    在這裡插入圖片描述
  • 單項鍊表不能自我刪除,需要靠輔助節點輔助刪除,而雙向連結串列可以實現自我刪除
    在這裡插入圖片描述
    在雙向連結串列中,每個節點不僅存放了下一個節點的地址,還存放了上一個節點的地址,因此,在雙向連結串列中,不僅可以實現順序遍歷,還可以實現逆序遍歷。

雙向連結串列的操作:

首先建立一個節點類,包含以下屬性:
(1)節點值:num
(2)前驅節點:pre
(3)後繼節點:next

//定義一個Node,每個Node物件就是一個節點
class Node2{
    public int num;
    public Node2 next;
//後繼節點:指向下一個節點 public Node2 pre; //前驅節點:指向前一個節點 public Node2(int num) { this.num = num; } public int getNum() { return num; } }

其次,我們需要一個雙向連結串列類,連結串列類先初始化一個頭節點,並提供獲取頭節點的方法

//建立一個雙線連結串列的類
class DoubleLinkedList{
    //先初始化一個頭節點,頭節點一般不要動,因為頭節點是為了指示連結串列的最頂端,如果不存在就無法找到整個連結串列
private Node2 head = new Node2(0); //不存放具體的資料 //返回頭節點 public Node2 getHead() { return head; } }

定義完畢後,我們就能開始編寫雙向連結串列的操作功能了:

  • 1.新增

思路:
(1)先找到雙向連結串列的最後這個節點
(2)將最後一個節點的next指向新的節點
(3)將新節點的pre指向原連結串列的最後一個節點

//新增節點,按序新增(不允許新增重複元素)
public void addNode(Node2 node){
    Node2 cur = head;
//令一個輔助節點從頭開始向後遍歷 while (true) { if (cur.next == null) { //當這個節點的下一個節點為null,說明走到了連結串列的最後, node.pre = cur; //當前節點是連結串列的最後一個節點,那麼將新節點插入連結串列的最後即可 cur.next = node; break; //插入完成退出方法 } else if(cur.next.num > node.getNum()){ //當某個節點的值大於新插入的節點的值時,將新節點插入 node.pre = cur; //將新節點的pre指向當前節點 node.next = cur.next; //新節點的next指向當前節點的下一個節點 cur.next.pre = node; //將當前節點的下一個節點的pre指向新插入的節點 cur.next = node; //將當前節點的next指向新插入的節點 break; //插入完成退出方法 } else if (cur.next.num == node.getNum()){ System.out.println(node.getNum()+"已存在!"); break; } cur = cur.next; } }
  • 2、遍歷

思路:遍歷的方式和單項鍊表一樣,既可以向前查詢,也可以向後查詢。

//遍歷雙向連結串列的方法
public void getList(Node2 head){
    if (head.next==null){
        System.out.println("連結串列空!");
        return;
    }
    Node2 cur = head.next;
    while (cur!=null){
        System.out.println(cur.getNum());
        cur = cur.next;
    }
}
  • 3.刪除

思路:
(1)直接找到要刪除的這個節點,
(2)將這個要被刪除節點的前一個節點的next指向被刪除節點的next;

  • (cur.pre.next = cur.next)

(3)將被刪除節點的下一個節點的pre指向被刪除節點的前一個節點,

  • (cur.next.pre = cur.pre)

但是需要注意一點,如果要刪除的是最後一個節點,就不能再對最後一個節點的下一個節點的前驅進行賦值,否則會引起空指標異常,最後一個節點不需要這一步操作

//刪除節點
public void delNode(int no){
    //判斷當前連結串列是否為空
    if (head.next == null){
        System.out.println("連結串列空!");
        return;
    }
    Node2 cur = head.next;   //輔助節點,單項鍊表中,先找待刪除節點的前一個節點才能再做刪除,雙向連結串列可以自刪除
    while (true){
        if (cur == null){
            System.out.println("未找到值為"+no+"的節點!");
            return;
        }
        if (cur.num == no){
            cur.pre.next = cur.next;
            if(cur.next != null) {
                //此段程式碼不能做最後一個節點的判斷,最後一個節點的下一個節點為null,會引起空指標異常,因此最後一個節點就不需要執行以下判斷
                cur.next.pre = cur.pre;
            }
            return;
        }
        cur = cur.next;
    }

}

測試程式碼:

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    DoubleLinkedList list = new DoubleLinkedList();
    //新增元素:
    for (int i = 0; i < 10; i++) {
        int count = new Random().nextInt(10);
        System.out.println("新增第"+i+1+"個元素:"+count);
        list.addNode(new Node2(count));
    }
    //遍歷連結串列所有資料
    System.out.println("連結串列展示:");
    list.getList(list.getHead());
    //刪除節點
    System.out.println("輸入你要刪除的節點:");
    list.delNode(sc.nextInt());
    //遍歷連結串列所有資料
    System.out.println("連結串列展示:");
    list.getList(list.getHead());
}

在這裡插入圖片描述
到此一個雙向連結串列的基本功能就完成了。