【小白學演算法】6.單連結串列的修改、刪除

把蘋果v咬哭發表於2021-03-26

接著上一章繼續來看單連結串列。
之前對單連結串列進行了遍歷、插入的操作,本章繼續用程式碼來實現修改以及刪除。

一、單連結串列的修改

修改結點資訊首先需要先找到對應的結點,接著上一章的程式碼,也就是英雄的排名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種情況的結果都符合預期。

三、單連結串列結構與順序儲存結構的優缺點

  1. 查詢
    單連結串列時間複雜度為O(n),而順序儲存結構則是O(1),更有優勢。
  2. 插入和刪除
    順序結構平均需要移動表長的一半的元素,時間複雜度為0(n)。
    而單連結串列在找到目標位置後,插入和刪除操作的時間複雜度是O(1),效率更高。

沒有完美的方案,都有自己的優勢,所以具體還是要根據實際需求來定。
比如說,需求是高頻查詢,增刪很少,順序結構更適合。反之,單連結串列結構更合適。

相關文章