完成效果:单链表的增,删,改
什么是链表
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
特点: 在内存中不是连续的,查找慢(从头开始依次查找)增删元素快
图解:
HeroNode 类分析
//每个 HeroNode 就是一个节点
public class HeroNode {
public int id;
public String name;
public String nickName;
//指向下一个节点
public HeroNode next;
public HeroNode(int no, String name, String nickName) {
this.id = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + id +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}
这个类很好理解,作为单链表的 bean 类
其中最关键的是 id 和 next 参数,其他的都是 HeroNode 的参数
增加元素
public class SingleLinkedList {
//头结点,不存放数据
public HeroNode head = new HeroNode(0, "", "");
//添加节点
public void add(HeroNode heroNode) {
//头结点不能移动,所以使用一个临时变量来保存
HeroNode temp = head;
//当 temp.next 一直!=null,则说明不是最后一个元素
//如果 temp.next == null 则 while 会自动结束,执行之后的代码
while (temp.next != null) {
//后移 temp
temp = temp.next;
}
//当退出 while 时,temp 指向链表最后一个位置
//然后将 temp.next 指向新的元素
temp.next = heroNode;
}
//显示链表所有数据
public void show() {
if (head.next == null) {
System.out.println("链表为空");
return;
}
//头结点不能动
HeroNode temp = head.next;
//如果 temp!=null 说明当前还不是最后一个,那么久循环遍历
while (temp != null) {
System.out.println(temp);
//后移动 temp
temp = temp.next;
}
}
}
使用:
linkedList.add(new HeroNode(1, "宋江", "及时雨"));
linkedList.add(new HeroNode(5, "秦明", "霹雳火"));
linkedList.add(new HeroNode(6, "柴进", "小旋风"));
linkedList.add(new HeroNode(3, "吴用", "智多星"));
linkedList.add(new HeroNode(2, "李逵", "黑旋风"));
linkedList.add(new HeroNode(4, "林冲", "豹子头"));
System.out.println("正常添加~");
linkedList.show();
运行结果为:
HeroNode{no=1, name='宋江', nickName='及时雨'}
HeroNode{no=5, name='秦明', nickName='霹雳火'}
HeroNode{no=6, name='柴进', nickName='小旋风'}
HeroNode{no=3, name='吴用', nickName='智多星'}
HeroNode{no=2, name='李逵', nickName='黑旋风'}
分析: 在单链表中,最核心的就是如下这段代码:
(增加,删除,修改都是 用过 while 来遍历所有数据的)
//当 temp.next 一直!=null,则说明不是最后一个元素
//如果 temp.next == null 则 while 会自动结束,执行之后的代码
while (temp.next != null) {
//后移 temp
temp = temp.next;
}
在单链表中,添加元素是从最后面添加的,所以需要while 到最后一个位置,最后一个位置的 next == null,所以当 while 循环结束时,就是最后一个元素的位置.
图解:
根据 ID从小大大排序 增加元素
先上代码,然后分析:
/**
* 添加节点 按照 id 来排序
*/
public void addID(HeroNode heroNode) {
//头结点不能移动,所以使用一个临时变量来遍历
HeroNode temp = head;
//存入的 heroNode 编号是否存在
boolean flag = false;
//temp.next != null就一直循环
while (temp.next != null) {
//当前的节点 > 传入的节点
if (temp.next.id > heroNode.id) {
/*
* 假设现在 temp.next = 6
* heroNode.no = 3
*
* 那么 heroNode.no 应该添加到 temp 和 temp.next 之间
*/
break;
} else if (temp.next.id == heroNode.id) {
//添加的编号存在
flag = true;
break;
}
//temp 后移
temp = temp.next;
}
if (flag) {
System.out.printf("%d 号已经存在,名字为:%s\n", heroNode.id, heroNode.name);
return;
}
//当退出 while 时,加入链表
heroNode.next = temp.next;
temp.next = heroNode;
}
使用:
linkedList.addID(new HeroNode(1, "宋江", "及时雨"));
linkedList.addID(new HeroNode(5, "秦明", "霹雳火"));
linkedList.addID(new HeroNode(5,"秦明","霹雳火"));
linkedList.addID(new HeroNode(6, "柴进", "小旋风"));
linkedList.addID(new HeroNode(3, "吴用", "智多星"));
linkedList.addID(new HeroNode(2, "李逵", "黑旋风"));
linkedList.addID(new HeroNode(4, "林冲", "豹子头"));
System.out.println("根据 ID 添加~");
linkedList.show();
运行结果为:
5 号已经存在,名字为:秦明
根据 ID 添加~
HeroNode{no=1, name='宋江', nickName='及时雨'}
HeroNode{no=2, name='李逵', nickName='黑旋风'}
HeroNode{no=3, name='吴用', nickName='智多星'}
HeroNode{no=4, name='林冲', nickName='豹子头'}
HeroNode{no=5, name='秦明', nickName='霹雳火'}
HeroNode{no=6, name='柴进', nickName='小旋风'}
根据 id 排序有 2 种情况:
-
当前 id 存在(不能添加)
-
当前 id 不存在,增加到合适的位置 假设现在单链表元素id 为(1,4,7,9,11),新增加的元素id为 5 ,那么 5 就应该增加到 4 和 7 之间
图解:
这部分不好理解,看不懂的话看视频
在来解释一下赋值的这两句话:
//当退出 while 时,加入链表
heroNode.next = temp.next;
temp.next = heroNode;
图解:
修改元素
/*
* 根据 id 修改编号
*/
public void upData(HeroNode heroNode) {
HeroNode temp = head;
//false 表示没有相同的 ID 不能更改
boolean flag = false;
//如果不为 null 就一直循环
while (temp.next != null) {
if (temp.id == heroNode.id) {
//如果 temp.id == heroNode.id 那么则代表可以更改
flag = true;
break;
}
//temp 后移动
temp = temp.next;
}
if (flag) {
temp.name = heroNode.name;
temp.nickName = heroNode.nickName;
} else {
System.out.printf("编号为:%d 名字为:%s 的英雄,不能更改\n", heroNode.id, heroNode.name);
}
}
使用:
linkedList.addID(new HeroNode(1, "宋江", "及时雨"));
linkedList.addID(new HeroNode(5, "秦明", "霹雳火"));
linkedList.addID(new HeroNode(6, "柴进", "小旋风"));
linkedList.addID(new HeroNode(3, "吴用", "智多星"));
linkedList.addID(new HeroNode(2, "李逵", "黑旋风"));
//测试相同的 id
linkedList.addID(new HeroNode(1, "李逵", "黑旋风"));
//测试不同的 id
linkedList.upData(new HeroNode(8, "李逵", "黑旋风"));
System.out.println("修改编号~");
linkedList.show();
运行结果为:
1 号已经存在,名字为:李逵
编号为:8 名字为:李逵 的英雄,不能更改
修改编号~
HeroNode{no=1, name='宋江', nickName='及时雨'}
HeroNode{no=2, name='李逵', nickName='黑旋风'}
HeroNode{no=3, name='吴用', nickName='智多星'}
HeroNode{no=5, name='秦明', nickName='霹雳火'}
HeroNode{no=6, name='柴进', nickName='小旋风'}
分析: 修改元素的前提就是链表中存在该元素才能修改
-
根据 id 来判断当前链表中是否存在相同的元素
- 相同则可以修改
- 不相同则不能修改
-
在方法中需要传入需要修改的值
-
修改元素的时候找到该元素的位置,然后修改即可
图解:
删除元素
删除元素代码:
/**
* 根据编号删除
*/
public void remove(int removeId) {
HeroNode temp = head;
//true 表示有可删除的编号
boolean flag = false;
while (temp.next != null) {
//删除元素是通过 next 值来接触练习的
//所以通过判断 next和传入的 id 如果相同则删除掉即可
if (temp.next.id == removeId) {
flag = true;
break;
}
temp = temp.next;
}
//true 有相同的 id,可以删除
if (flag) {
//直接指向下一个元素,就完成的删除.
temp.next = temp.next.next;
}else{
System.out.printf("编号为:%d,的英雄不存在,不能删除\n",removeId);
}
}
使用:
//删除节点
private static void initRemove(SingleLinkedList linkedList) {
linkedList.addID(new HeroNode(1, "宋江", "及时雨"));
linkedList.addID(new HeroNode(5, "秦明", "霹雳火"));
linkedList.addID(new HeroNode(6, "柴进", "小旋风"));
linkedList.addID(new HeroNode(3, "吴用", "智多星"));
linkedList.addID(new HeroNode(2, "李逵", "黑旋风"));
linkedList.remove(1);
linkedList.remove(2);
linkedList.remove(3);
linkedList.remove(4);
linkedList.remove(5);
System.out.println("删除节点~");
linkedList.show();
}
运行结果为:
编号为:4,的英雄不存在,不能删除
删除节点~
HeroNode{no=6, name='柴进', nickName='小旋风'}
分析: 删除元素和替换元素思路是一样的,首先需要根据 id找到删除的位置,然后把当前指向位置指向下一个位置即可
如果需要删除元素二,那么只需要吧 id = 1 的 next 指向 id = 3 (hero.next = hero.next.next)
猜你喜欢:
原创不易,您的点赞加就是对我最大的支持!