接着上一章继续来看单链表。
之前对单链表进行了遍历、插入的操作,本章继续用代码来实现修改以及删除。
一、单链表的修改
修改结点信息首先需要先找到对应的结点,接着上一章的代码,也就是英雄的排名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),更有优势。
2.插入和删除
顺序结构平均需要移动表长的一半的元素,时间复杂度为0(n)。
而单链表在找到目标位置后,插入和删除操作的时间复杂度是O(1),效率更高。
没有完美的方案,都有自己的优势,所以具体还是要根据实际需求来定。
比如说,需求是高频查找,增删很少,顺序结构更适合。反之,单链表结构更合适。