接著上一章繼續來看單連結串列。
之前對單連結串列進行了遍歷、插入的操作,本章繼續用程式碼來實現修改以及刪除。
一、單連結串列的修改
修改結點資訊首先需要先找到對應的結點,接著上一章的程式碼,也就是英雄的排名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),效率更高。
沒有完美的方案,都有自己的優勢,所以具體還是要根據實際需求來定。
比如說,需求是高頻查詢,增刪很少,順序結構更適合。反之,單連結串列結構更合適。