資料結構之連結串列(LinkedList)(二)
阿新 • • 發佈:2019-06-04
資料結構之連結串列(LinkedList)(一)
雙鏈表
上一篇講述了單鏈表是通過next 指向下一個節點,那麼雙鏈表就是指不止可以順序指向下一個節點,還可以通過prior域逆序指向上一個節點
示意圖:
那麼怎麼來實現雙鏈表的增刪改查操作呢。
分析:
1) 遍歷 方和 單鏈表一樣,只是可以向前,也可以向後查詢
2) 新增 (預設新增到雙向連結串列的最後)
① 先找到雙向連結串列的最後這個節點
② temp.next = newStuNode
③ newStuNode.prior = temp;
3) 修改 思路和 原來的單向連結串列一樣.
4) 刪除
①因為是雙向連結串列,因此,我們可以實現自我刪除某個節點
② 直接找到要刪除的這個節點,比如temp
③ temp.prior.next = temp.next
④ temp.next.prior= temp.prior;
實現程式碼:
新增&遍歷:
預設新增在連結串列最後一個。
// 新增一個節點到雙向連結串列的最後. public void add(StuNode2 stuNode2){ // 因為head節點不能動,因此我們需要一個輔助遍歷 temp StuNode2 temp = head; // 遍歷連結串列,找到最後 while (true) { // 找到連結串列的最後 if (temp.next == null) {// break; } // 如果沒有找到最後, 將將temp後移 temp = temp.next; } // 當退出while迴圈時,temp就指向了連結串列的最後 // 形成一個雙向連結串列 temp.next = stuNode2; stuNode2.prior = temp; }
//遍歷雙向列表的方法 和單項列表一致 //顯示連結串列[遍歷] public void list() { //判斷連結串列是否為空 if(head.next == null) { System.out.println("連結串列為空"); return; } //因為頭節點,不能動,因此我們需要一個輔助變數來遍歷 StuNode2 temp = head.next; while(true) { //判斷是否到連結串列最後 if(temp == null) { break; } //輸出節點的資訊 System.out.println(temp); //將temp後移, 一定小心 temp = temp.next; } }
public static void main(String[] args) { //進行測試 //先建立節點 StuNode2 stu1 = new StuNode2(1, "張三", "85"); StuNode2 stu2 = new StuNode2(2, "李四", "87"); StuNode2 stu3 = new StuNode2(3, "小明", "70"); StuNode2 stu4 = new StuNode2(4, "小紅", "90"); //建立要給連結串列 DoubleLinkedList doubleLinkedList = new DoubleLinkedList(); //加入 doubleLinkedList.add(stu1); doubleLinkedList.add(stu2); doubleLinkedList.add(stu3); doubleLinkedList.add(stu4); System.out.println("原始雙鏈表資料 " ); doubleLinkedList.list();; }main
原始雙鏈表資料 StuNode [stuNo=1, name=張三, mark=85] StuNode [stuNo=2, name=李四, mark=87] StuNode [stuNo=3, name=小明, mark=70] StuNode [stuNo=4, name=小紅, mark=90]輸出
根據序號排序新增
上面新增是預設新增到最後一個節點,那麼要求根據序號預設排序新增呢,其實和單鏈表是一樣思路
public void addByOrder(StuNode2 stuNode2){ StuNode2 temp = head; boolean flag = false; while (true){ if (temp.next == null){ break; } if (temp.next.stuNo>stuNode2.stuNo){//位置找到 break; }else if (temp.stuNo == stuNode2.stuNo){ flag=true; break; } temp =temp.next; } if (flag){ System.out.printf("準備插入的學生 %d 已經存在了, 不能加入\n", stuNode2.stuNo); }else{ stuNode2.next=temp.next; temp.next=stuNode2; stuNode2.prior=temp; if(temp.next != null){ temp.next.prior=stuNode2; } } }程式碼
修改:
// 修改一個節點的內容, 可以看到雙向連結串列的節點內容修改和單向連結串列一樣 // 只是 節點型別改成 StuNode2 public void update(StuNode2 newStuNode) { // 判斷是否空 if (head.next == null) { System.out.println("連結串列為空~"); return; } // 找到需要修改的節點, 根據stuNo編號 // 定義一個輔助變數 StuNode2 temp = head.next; boolean flag = false; // 表示是否找到該節點 while (true) { if (temp == null) { break; // 已經遍歷完連結串列 } if (temp.stuNo == newStuNode.stuNo) { // 找到 flag = true; break; } temp = temp.next; } // 根據flag 判斷是否找到要修改的節點 if (flag) { temp.name = newStuNode.name; temp.mark = newStuNode.mark; } else { // 沒有找到 System.out.printf("沒有找到 學號 %d 的節點,不能修改\n", newStuNode.stuNo); } }修改程式碼
public static void main(String[] args) { //進行測試 //先建立節點 StuNode2 stu1 = new StuNode2(1, "張三", "85"); StuNode2 stu2 = new StuNode2(2, "李四", "87"); StuNode2 stu3 = new StuNode2(3, "小明", "70"); StuNode2 stu4 = new StuNode2(4, "小紅", "90"); //建立要給連結串列 DoubleLinkedList doubleLinkedList = new DoubleLinkedList(); //加入 doubleLinkedList.add(stu1); doubleLinkedList.add(stu2); doubleLinkedList.add(stu3); doubleLinkedList.add(stu4); System.out.println("原始雙鏈表資料 " ); doubleLinkedList.list();; //修改3號的分數 StuNode2 stu = new StuNode2(3,"小明","99"); doubleLinkedList.update(stu); System.out.println("修改後的連結串列"); doubleLinkedList.list();; }main
原始雙鏈表資料 StuNode [stuNo=1, name=張三, mark=85] StuNode [stuNo=2, name=李四, mark=87] StuNode [stuNo=3, name=小明, mark=70] StuNode [stuNo=4, name=小紅, mark=90] 修改後的連結串列 StuNode [stuNo=1, name=張三, mark=85] StuNode [stuNo=2, name=李四, mark=87] StuNode [stuNo=3, name=小明, mark=99] StuNode [stuNo=4, name=小紅, mark=90]輸出
刪除:
上篇單鏈表的思路是找到要刪除節點的前一個節點,然後待刪除節點的前一個節點直接指向待刪除節點的後一個節點,隱藏待刪除的節點,從而達到刪除目的。
那麼雙鏈表可以直接找到待刪除節點temp,通過逆指向 temp.prior 找到待刪除節點的上一個節點,然後順指向temp.prior.next 指向待刪除節點的下一個節點temp.next
也就是 temp.prior.next = temp.next。同時要修改 待刪除節點的下一個節點的逆指向 指向待刪除節點的上一個節點,也就是temp.next.prior= temp.prior;
示意圖:
// 從雙向連結串列中刪除一個節點, // 說明 // 1 對於雙向連結串列,我們可以直接找到要刪除的這個節點 // 2 找到後,自我刪除即可 public void del(int stuNo) { // 判斷當前連結串列是否為空 if (head.next == null) {// 空連結串列 System.out.println("連結串列為空,無法刪除"); return; } StuNode2 temp = head.next; // 輔助變數(指標) boolean flag = false; // 標誌是否找到待刪除節點的 while (true) { if (temp == null) { // 已經到連結串列的最後 break; } if (temp.stuNo == stuNo) { // 找到的待刪除節點的前一個節點temp flag = true; break; } temp = temp.next; // temp後移,遍歷 } // 判斷flag if (flag) { // 找到 // 可以刪除 // temp.next = temp.next.next;[單向連結串列] temp.prior.next = temp.next; // 如果是最後一個節點,就不需要執行下面這句話,否則出現空指標 if (temp.next != null) { temp.next.prior = temp.prior; } } else { System.out.printf("要刪除的 %d 節點不存在\n", stuNo); } }刪除程式碼
public static void main(String[] args) { //進行測試 //先建立節點 StuNode2 stu1 = new StuNode2(1, "張三", "85"); StuNode2 stu2 = new StuNode2(2, "李四", "87"); StuNode2 stu3 = new StuNode2(3, "小明", "70"); StuNode2 stu4 = new StuNode2(4, "小紅", "90"); //建立要給連結串列 DoubleLinkedList doubleLinkedList = new DoubleLinkedList(); //加入 doubleLinkedList.add(stu1); doubleLinkedList.add(stu2); doubleLinkedList.add(stu3); doubleLinkedList.add(stu4); System.out.println("原始雙鏈表資料 " ); doubleLinkedList.list(); //刪除3號資料 doubleLinkedList.del(3); System.out.println("刪除後的連結串列 " ); doubleLinkedList.list(); }main
原始雙鏈表資料 StuNode [stuNo=1, name=張三, mark=85] StuNode [stuNo=2, name=李四, mark=87] StuNode [stuNo=3, name=小明, mark=70] StuNode [stuNo=4, name=小紅, mark=90] 刪除後的連結串列 StuNode [stuNo=1, name=張三, mark=85] StuNode [stuNo=2, name=李四, mark=87] StuNode [stuNo=4, name=小紅, mark=90]輸出
&n