【小白学算法】6.单链表的修改、删除

简介: 【小白学算法】6.单链表的修改、删除

接着上一章继续来看单链表。


之前对单链表进行了遍历、插入的操作,本章继续用代码来实现修改以及删除。


一、单链表的修改


修改结点信息首先需要先找到对应的结点,接着上一章的代码,也就是英雄的排名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、删除结点


要删除结点,依然要先找到这个结点。


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),效率更高。


没有完美的方案,都有自己的优势,所以具体还是要根据实际需求来定。


比如说,需求是高频查找,增删很少,顺序结构更适合。反之,单链表结构更合适。

相关文章
|
4天前
|
存储 算法 C语言
【数据结构与算法 刷题系列】合并两个有序链表
【数据结构与算法 刷题系列】合并两个有序链表
|
12天前
|
存储 算法 Go
算法学习:数组 vs 链表
算法学习:数组 vs 链表
17 0
|
20天前
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
5天前
|
机器学习/深度学习 算法 C语言
【C/数据结构与算法】:10道链表经典OJ
【C/数据结构与算法】:10道链表经典OJ
9 1
|
12天前
|
算法 Java
[Java·算法·中等] LeetCode21. 合并两个有序链表
[Java·算法·中等] LeetCode21. 合并两个有序链表
15 2
|
24天前
|
存储 算法
数据结构和算法学习记录——二叉树的存储结构&二叉树的递归遍历(顺序存储结构、链表存储结构、先序中序后序递归遍历)
数据结构和算法学习记录——二叉树的存储结构&二叉树的递归遍历(顺序存储结构、链表存储结构、先序中序后序递归遍历)
12 0
数据结构和算法学习记录——二叉树的存储结构&二叉树的递归遍历(顺序存储结构、链表存储结构、先序中序后序递归遍历)
|
4天前
|
算法 Java
Java数据结构与算法:双向链表
Java数据结构与算法:双向链表
|
4天前
|
算法 Java
Java数据结构与算法:循环链表
Java数据结构与算法:循环链表
|
4天前
|
算法
【数据结构与算法 刷题系列】求带环链表的入环节点(图文详解)
【数据结构与算法 刷题系列】求带环链表的入环节点(图文详解)
|
4天前
|
算法
【数据结构与算法 刷题系列】判断链表是否有环(图文详解)
【数据结构与算法 刷题系列】判断链表是否有环(图文详解)