上一篇講述了單鏈表是經過next 指向下一個節點,那麼雙鏈表就是指不止能夠順序指向下一個節點,還能夠經過prior域逆序指向上一個節點html
示意圖:數據結構
那麼怎麼來實現雙鏈表的增刪改查操做呢。ide
分析:測試
1) 遍歷 方和 單鏈表同樣,只是能夠向前,也能夠向後查找spa
2) 添加 (默認添加到雙向鏈表的最後)3d
① 先找到雙向鏈表的最後這個節點指針
② temp.next = newStuNodecode
③ newStuNode.prior = temp;htm
3) 修改 思路和 原來的單向鏈表同樣.blog
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();; }
原始雙鏈表數據 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();; }
原始雙鏈表數據 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(); }
原始雙鏈表數據 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]