1. 程式人生 > 實用技巧 >資料結構-雙向連結串列

資料結構-雙向連結串列

資料結構-雙向連結串列

為什麼要有雙向連結串列?

單向連結串列的缺點分析:

1) 單向連結串列,查詢的方向只能是一個方向,而雙向連結串列可以向前或者向後查詢。

2) 單向連結串列不能自我刪除,需要靠輔助節點 ,而雙向連結串列,則可以自我刪除,所以前面我們單鏈表刪除 時節點,總是找到 temp,temp 是待刪除節點的前一個節點(認真體會).

分析 雙向連結串列的遍歷,新增,修改,刪除的操作思路===》程式碼實現

1) 遍歷 方和 單鏈表一樣,只是可以向前,也可以向後查詢

2) 新增 (預設新增到雙向連結串列的最後)

   (1) 先找到雙向連結串列的最後這個節點

  (2)temp.next=newHeroNode

  (3)newHeroNode.pre=temp;

3) 修改 思路和 原來的單向連結串列一樣.

4) 刪除

  (1) 因為是雙向連結串列,因此,我們可以實現自我刪除某個節點

  (2) 直接找到要刪除的這個節點,比如 temp

  (3) temp.pre.next=temp.next

   (4)temp.next.pre=temp.pre; //這裡需要判斷temp.next != null

新增節點

(1)直接新增到鏈尾

(2)按照順序插入

刪除節點

原始碼

package com.orz.LinkList;

/**
 * @author orz
 * @create 2020-10-24 22:11
 
*/ public class DoubleLinkedListTest { public static void main(String[] args) { DoubleLinkedList link=new DoubleLinkedList(); HeroSingleNode node1=new HeroSingleNode(1,"宋江","及時雨"); HeroSingleNode node2=new HeroSingleNode(2,"吳用","智多星"); HeroSingleNode node3=new HeroSingleNode(3,"林沖","豹子頭"); HeroSingleNode node4
=new HeroSingleNode(4,"李逵","黑旋風"); DoubleLinkedList link2=new DoubleLinkedList(); //不按順序新增測試 link2.add(node4); link2.add(node2); link2.add(node1); link2.add(node3); System.out.println("直接新增到鏈尾"); DoubleLinkedList.showHeroLink(link2); System.out.println("-------------------------------------------------------"); //按順序新增測試 link.addHeroNodeOrderById(node3); link.addHeroNodeOrderById(node2); link.addHeroNodeOrderById(node1); link.addHeroNodeOrderById(node4); System.out.println("按順序新增"); DoubleLinkedList.showHeroLink(link); System.out.println("-------------------------------------------------------"); HeroSingleNode newnode4=new HeroSingleNode(4,"李xx","黑xx"); link.updateHeroNode(newnode4); System.out.println("修改節點資訊"); DoubleLinkedList.showHeroLink(link); System.out.println("-------------------------------------------------------"); link.deleteHeroNodeById(1); System.out.println("刪除節點1"); DoubleLinkedList.showHeroLink(link); System.out.println("-------------------------------------------------------"); } } class DoubleLinkedList{ private HeroSingleNode head=new HeroSingleNode(0,null,null); public HeroSingleNode getHead() { return head; } //遍歷雙向連結串列,跟單鏈表一樣 public static void showHeroLink(DoubleLinkedList link) { if (link.head.next == null) { System.out.println("連結串列為空!!!"); return; } HeroSingleNode temp = link.head.next; while (temp != null) { System.out.println(temp); temp = temp.next; } } //新增節點 //第一種,預設新增到鏈尾 public void add(HeroSingleNode node) { //因為head不能動,所以需要一個輔助節點變數 HeroSingleNode temp = head; //標記待新增的節點是否已經存在 boolean flag = false; //遍歷連結串列,找到最後 while (true) { //如果節點的next為空說明該節點就是最後一個節點 if (temp.next == null) { break; } if (temp.next.id == node.id) { flag = true; break; } //否則指標下移 temp = temp.next; } if (flag) { System.out.println("新增失敗,需要新增id為"+node.id+"的節點已經存在了!!!"); return; } //加入新節點,雙向建立聯絡 temp.next = node; node.pre=temp; } /** * 新增節點資訊,第二種:根據排名將英雄插入到指定位置,按照id從小到大排序 */ public void addHeroNodeOrderById(HeroSingleNode node) { //如果還沒有任何一個節點,直接插入到head後面 if (head.next == null) { //建立雙向聯絡 head.next = node; node.pre=head; return; } //因為頭節點不能動,所以我們仍然通過一個輔助指標(變數)來幫助找到新增的位置 HeroSingleNode temp = head; //標記待新增的節點是否已經存在 boolean flag = false; while (true) { //說明 temp 已經在連結串列的最後一個了 if (temp.next == null) { break; } //節點已經存在 if (temp.next.id == node.id) { flag = true; break; } //位置找到,就在 temp 的後面插入 if (temp.next.id > node.id) { break; } temp = temp.next; } if (flag) { System.out.println("新增失敗,需要新增id為" + node.id + "的節點已經存在了!!!"); } else { //插入的節點與temp的下一個節點建立聯絡 if (temp.next != null) { temp.next.pre=node; } node.next=temp.next; //插入的節點與temp建立聯絡 node.pre=temp; temp.next=node; } } /** * 修改連結串列節點資料,id不要動,跟單鏈表一樣 */ public void updateHeroNode(HeroSingleNode node) { if(head.next==null) { System.out.println("連結串列為空"); return; } HeroSingleNode temp=head.next; boolean flag=false; while (true) { if(temp==null) { break; } if(temp.id==node.id) { flag=true; break; } temp=temp.next; } if (flag) { temp.heroName=node.heroName; temp.nikeName=node.nikeName; } else { System.out.println("id為"+node.id+"的節點不存在!!!"); } } /** * 刪除節點 * //1.head 不能動,因此我們需要一個 temp 輔助節點找到待刪除節點的 * //2. 說明我們在比較時,是 temp.id 和 需要刪除的節點的 id 比較 */ public void deleteHeroNodeById(int id) { if(head.next==null) { System.out.println("連結串列為空"); return; } HeroSingleNode temp=head.next; // 標誌是否找到待刪除節點的 boolean flag=false; while (true) { //已經到了連結串列最後一個的next if(temp==null) { break; } if(temp.id==id) { flag=true; break; } temp=temp.next; } if(flag) { //temp的前一個節點和後一個節點建立聯絡 temp.pre.next=temp.next; //這裡可能有問題,如果刪除最後一個節點 if (temp.next!=null) { temp.next.pre=temp.pre; } } else { System.out.println("連結串列中沒有id為"+id+"的節點資料"); } } } class HeroSingleNode{ public int id; //英雄名 public String heroName; //英雄暱稱 public String nikeName; //next域 public HeroSingleNode next; //指向前一個節點 public HeroSingleNode pre; public HeroSingleNode() { } public HeroSingleNode(int id, String heroName, String nikeName) { this.id = id; this.heroName = heroName; this.nikeName = nikeName; } @Override public String toString() { return "HeroSingleNode{" + "id=" + id + ", heroName='" + heroName + '\'' + ", nikeName='" + nikeName + '\'' + '}'; } }
View Code