1. 程式人生 > >【小白學演算法】6.單鏈表的修改、刪除

【小白學演算法】6.單鏈表的修改、刪除

接著[上一章](https://www.cnblogs.com/pingguo-softwaretesting/p/14535112.html)繼續來看單鏈表。 之前對單鏈表進行了遍歷、插入的操作,本章繼續用程式碼來實現修改以及刪除。 ### 一、單鏈表的修改 修改結點資訊首先需要先找到對應的結點,接著上一章的程式碼,也就是英雄的排名no是不能修改的,要用來找結點。 其他的資訊就可以動了。 另外,還要考慮到單鏈表中找不到對應要修改的結點的情況。這裡程式碼就不全貼出來了,現在繼續在`SingleLinkedList`類 中增加修改結點資訊的方法: ``` // 修改結點資訊 // 根據結點的no來修改即可 public void update(HeroNode newHeroNode) { // 判斷連結串列是否為空 if (headNode.next == null) { System.out.println("連結串列為空"); return; } // 藉助輔助變數temp HeroNode temp = headNode.next; boolean flag = false; // 表示是否可以找到要修改的結點 while (true) { if (temp == null) { break; // 遍歷結束 } if (temp.no == newHeroNode.no) { // 找到了對應的結點 flag = true; break; } temp = temp.next; } // 根據flag 判斷是否已經找到對應要修改的結點 if (flag) { temp.name = newHeroNode.name; temp.nickname = newHeroNode.nickname; } else { System.out.printf("未找到編號%d的結點,不可修改\n", newHeroNode.no); } } ``` 在main方法中修改測試程式碼,看看結果是否符合預期。 ``` public static void main(String[] args) { // 測試 HeroNode hero1 = new HeroNode(1, "易大師","無極劍聖"); HeroNode hero2 = new HeroNode(2, "李青","盲僧"); HeroNode hero3 = new HeroNode(3, "艾希","寒冰射手"); HeroNode hero4 = new HeroNode(4, "菲奧娜","無雙劍姬"); // 建立連結串列 SingleLinkedList singleLinkedList = new SingleLinkedList(); // 加入物件結點 singleLinkedList.addByNo(hero1); singleLinkedList.addByNo(hero4); singleLinkedList.addByNo(hero2); singleLinkedList.addByNo(hero3); // 顯示連結串列內容 singleLinkedList.linkList(); // 測試修改 HeroNode hero5 = new HeroNode(2, "李青","瞎子"); singleLinkedList.update(hero5); System.out.println("修改後的連結串列:"); singleLinkedList.linkList(); } ``` 執行結果: ``` HeroNode{no=1, name='易大師', nickname='無極劍聖'} HeroNode{no=2, name='李青', nickname='盲僧'} HeroNode{no=3, name='艾希', nickname='寒冰射手'} HeroNode{no=4, name='菲奧娜', nickname='無雙劍姬'} 修改後的連結串列: HeroNode{no=1, name='易大師', nickname='無極劍聖'} HeroNode{no=2, name='李青', nickname='瞎子'} HeroNode{no=3, name='艾希', nickname='寒冰射手'} HeroNode{no=4, name='菲奧娜', nickname='無雙劍姬'} Process finished with exit code 0 ``` 繼續修改一個不存在的結點:`HeroNode hero5 = new HeroNode(11, "李青","瞎子");` 測試結果: ``` HeroNode{no=1, name='易大師', nickname='無極劍聖'} HeroNode{no=2, name='李青', nickname='盲僧'} HeroNode{no=3, name='艾希', nickname='寒冰射手'} HeroNode{no=4, name='菲奧娜', nickname='無雙劍姬'} 未找到編號11的結點,不可修改 修改後的連結串列: HeroNode{no=1, name='易大師', nickname='無極劍聖'} HeroNode{no=2, name='李青', nickname='盲僧'} HeroNode{no=3, name='艾希', nickname='寒冰射手'} HeroNode{no=4, name='菲奧娜', nickname='無雙劍姬'} Process finished with exit code 0 ``` ### 二、單鏈表的刪除 #### 1、刪除結點 要刪除結點,依然要先找到這個結點。 ![](https://img2020.cnblogs.com/blog/1268169/202103/1268169-20210321211424309-229454770.png) 如圖所示,我要刪除結點4,藉助temp來遍歷,找到要刪除的結點。但是,temp不能指在結點4,得指向結點4的前一個。 因為這是個單向連結串列,結點4裡記錄的是下一個結點的位置資訊,所以在結點4這是刪不掉的。應該指在結點1,這樣就可以 修改結點1的next指標,繞過結點4,指向結點8。 而此時的結點4,由於沒有其他引用指向它,於是被垃圾回收機制回收,到此就完成了結點4的刪除了。 繼續用程式碼來模擬,新增一個結點刪除的方法: ``` // 刪除結點 public void delete(int no) { HeroNode temp = headNode; boolean flag = false; // 標記是否找到待刪除的結點的前一個結點 while (true) { if (temp.next == null) { break; } if (temp.next.no == no) { // 找到待刪除結點的前一個結點 flag = true; break; } temp = temp.next; // temp後移操作 } if (flag) { temp.next = temp.next.next; } else { System.out.printf("要刪除的結點%d 不存在\n", no); } } ``` 測試刪除,我把首尾的1和4刪掉。 ``` 刪除後的連結串列: HeroNode{no=2, name='李青', nickname='瞎子'} HeroNode{no=3, name='艾希', nickname='寒冰射手'} Process finished with exit code 0 ``` 我把連結串列裡的結點全刪掉: ``` 刪除後的連結串列: 連結串列為空 Process finished with exit code 0 ``` 2種情況的結果都符合預期。 ### 三、單鏈表結構與順序儲存結構的優缺點 1. 查詢 單鏈表時間複雜度為O(n),而順序儲存結構則是O(1),更有優勢。 2. 插入和刪除 順序結構平均需要移動表長的一半的元素,時間複雜度為0(n)。 而單鏈表在找到目標位置後,插入和刪除操作的時間複雜度是O(1),效率更高。 沒有完美的方案,都有自己的優勢,所以具體還是要根據實際需求來定。 比如說,需求是高頻查詢,增刪很少,順序結構更適合。反之,單鏈表結構更