【小白學演算法】6.單鏈表的修改、刪除
阿新 • • 發佈:2021-03-26
接著[上一章](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),效率更高。
沒有完美的方案,都有自己的優勢,所以具體還是要根據實際需求來定。
比如說,需求是高頻查詢,增刪很少,順序結構更適合。反之,單鏈表結構更