接着上一章繼續來看單鏈表。
之前對單鏈表進行了遍歷、插入的操作,本章繼續用代碼來實現修改以及刪除。
一、單鏈表的修改
修改結點信息首先需要先找到對應的結點,接着上一章的代碼,也就是英雄的排名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、刪除結點
要刪除結點,依然要先找到這個結點。
如圖所示,我要刪除結點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種情況的結果都符合預期。
三、單鏈表結構與順序存儲結構的優缺點
- 查找
單鏈表時間復雜度為O(n),而順序存儲結構則是O(1),更有優勢。 - 插入和刪除
順序結構平均需要移動表長的一半的元素,時間復雜度為0(n)。
而單鏈表在找到目標位置后,插入和刪除操作的時間復雜度是O(1),效率更高。
沒有完美的方案,都有自己的優勢,所以具體還是要根據實際需求來定。
比如說,需求是高頻查找,增刪很少,順序結構更適合。反之,單鏈表結構更合適。