文章目录
- 1、什么是链表?
- 2、链表代码的实现
- 2.1、链表尾部加入数据的主程序的实现(测试使用)
- 2.2、结点的实现
- 2.3、单链表以及相关功能的实现
- 2.3.1、实现单链表全部代码
- 2.3.2、实现链表的尾部加入数据
- 2.3.3、将链表显示到控制台
- 2.4、链表程序升级:按照编号的顺序进行添加
- 2.4.1、按照编号进行添加节点的方法实现
- 2.4.2、按照 no 插入节点的主程序 main() 的实现
- 2.5、对于链表的更新数据、删除节点
- 2.5.1、链表的更新
- (1)实现思路
- (2)实现代码
- (3)方法的调用
- 2.5.2、链表的节点的删除
- (1)实现思路
- (2)实现代码
- (3)方法的调用
1、什么是链表?
2、链表代码的实现
2.1、链表尾部加入数据的主程序的实现(测试使用)
public class SingleLinkedListDemo {
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, "林 冲", "豹子头");
HeroNode hero5 = new HeroNode(5, "张 三", "三 儿");
// 创建一个链表
SingleLinkedList singleLinkedList = new SingleLinkedList();
// 进行加入
singleLinkedList.add(hero1);
singleLinkedList.add(hero2);
singleLinkedList.add(hero3);
singleLinkedList.add(hero4);
singleLinkedList.add(hero5);
// 显示
singleLinkedList.list();
}
}
2.2、结点的实现
class HeroNode {
public int no;
public String name;
public String nickname;
public HeroNode next; // 指向下一个节点
// 创建类的构造器
public HeroNode(int hNo, String hName, String hNickname) {
this.no = hNo;
this.name = hName;
this.nickname = hNickname;
}
// 为了显示方法,重新进行 toString 方法
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
", next=" + next +
'}';
}
}
2.3、单链表以及相关功能的实现
2.3.1、实现单链表全部代码
package com.luobin.DataStructure.单链表;
/**
* @author LuoBin
* @version 1.0
* @date 2021/8/3 11:09 下午
*/
// 创建SingleLinkedList 的单链表,进行任务的管理
public class SingleLinkedList {
// 初始化一个头节点 , 头节点不动 , 不存放具体的数据
private HeroNode head = new HeroNode(0, "", "");
// 添加节点到单项链表
public void add(HeroNode heroNode) {
// 当不考虑编号的顺序时候
// 1、找到当前链表的最后节点
// 2、将最后的节点的next 指向新的节点
// 因为头节点不能动,需要辅助指针temp ,对于链表进行遍历
// 此处的 head 指的是 存储对象的引用地址,是地址的传递,起到一定的指针的作用
HeroNode temp = head;
// 进行遍历链表的操作
while (true) {
if (temp.next == null) {
break;
}
// 辅助指针没有到最后的时候,将其向后面进行移动
// next 指的是 相关节点对应的下一个节点的存储位置
temp = temp.next;
}
// 当退出最后的 while 循环时候,temp 指向了链表的最后面;
// 将最后这个节点的 next 指向到新的节点 进行链接操作;
temp.next = heroNode;
}
// 显示链表 进行遍历
public void list() {
// 判断链表是否为空
if (head.next == null) {
System.out.println("链表为空");
return;
}
// 头节点的位置不能移动,需要创建使用一个辅助变量进行遍历
HeroNode temp = head.next;
while (true) {
// 判断是否为最后
if (temp == null) {
break;
}
// 输出节点的信息
System.out.println(temp);
// 将temp 进行后移
temp = temp.next;
}
}
// 使用第二种添加方式,使用排名将英雄加入到指定的位置
// 有了排名,添加失败,给出提示
public void addByOrder(HeroNode heroNode) {
// 头节点不能动,使用辅助指针进行处理
// 单链表,找到的temp 是位于添加位置的前一个节点
HeroNode temp = head;
boolean flag = false; // flag 标志添加的位置是否存在,默认为 false
while (true) { // 说明此时 temp 处于链表的后面
if (temp.next == null) {
break;
}
if (temp.next.no > heroNode.no) {// 位置找到,在temp 的后面进行插入
break;
} else if (temp.next.no == heroNode.no) { // 说明添加的heroNode 的编号已经存在
flag = true; // 说明编号是存在的
break;
}
temp = temp.next;// 后移,遍历当前的链表 后移的前提是,前面的位置都没有找到
}
if (flag) {
System.out.printf("准备插入的英雄编号%d已经存在,不能加入", heroNode.no);
} else {
// 插入到链表中,temp 的后面
heroNode.next = temp.next; // ( 原始的temp.next 是与下一个元素连接的 )
temp.next = heroNode; // (此时的temp.next 重新向着下一个新的节点进行连接)
// temp 充当的就是指针的作用
}
}
}
2.3.2、实现链表的尾部加入数据
public class SingleLinkedList {
// 初始化一个头节点 , 头节点不动 , 不存放具体的数据
private HeroNode head = new HeroNode(0, "", "");
// 添加节点到单项链表
public void add(HeroNode heroNode) {
// 当不考虑编号的顺序时候
// 1、找到当前链表的最后节点
// 2、将最后的节点的next 指向新的节点
// 因为头节点不能动,需要辅助指针temp ,对于链表进行遍历
// 此处的 head 指的是 存储对象的引用地址,是地址的传递,起到一定的指针的作用
HeroNode temp = head;
// 进行遍历链表的操作
while (true) {
if (temp.next == null) {
break;
}
// 辅助指针没有到最后的时候,将其向后面进行移动
// next 指的是 相关节点对应的下一个节点的存储位置
temp = temp.next;
}
// 当退出最后的 while 循环时候,temp 指向了链表的最后面;
// 将最后这个节点的 next 指向到新的节点 进行链接操作;
temp.next = heroNode;
}
}
2.3.3、将链表显示到控制台
// 显示链表 进行遍历
public void list() {
// 判断链表是否为空
if (head.next == null) {
System.out.println("链表为空");
return;
}
// 头节点的位置不能移动,需要创建使用一个辅助变量进行遍历
HeroNode temp = head.next;
while (true) {
// 判断是否为最后
if (temp == null) {
break;
}
// 输出节点的信息
System.out.println(temp);
// 将temp 进行后移
temp = temp.next;
}
}
2.4、链表程序升级:按照编号的顺序进行添加
辅助变量 辅助指针 是同一个东西
1、首先找到新添加的节点的位置,通过辅助变量进行获取(指针)(通过遍历进行解决)
2、新的节点.
next = temp.next;
(
意思为temp.next 指向的是数据 4 ,新的节点.next也是指向数据 4 的,建立起来了新节点与后面之间的关系;
)
3、temp.next = 新的节点;
2.4.1、按照编号进行添加节点的方法实现
// 使用第二种添加方式,使用排名将英雄加入到指定的位置
// 有了排名,添加失败,给出提示
public void addByOrder(HeroNode heroNode) {
// 头节点不能动,使用辅助指针进行处理
// 单链表,找到的temp 是位于添加位置的前一个节点
HeroNode temp = head;
boolean flag = false; // flag 标志添加的位置是否存在,默认为 false
while (true) { // 说明此时 temp 处于链表的后面
if (temp.next == null) {
break;
}
if (temp.next.no > heroNode.no) {// 位置找到,在temp 的后面进行插入
break;
} else if (temp.next.no == heroNode.no) { // 说明添加的heroNode 的编号已经存在
flag = true; // 说明编号是存在的
break;
}
temp = temp.next;// 后移,遍历当前的链表
}
if (flag) {
System.out.printf("准备插入的英雄编号%d已经存在,不能加入", heroNode.no);
} else {
// 插入到链表中,temp 的后面
heroNode.next = temp.next;
temp.next = heroNode;
}
}
2.4.2、按照 no 插入节点的主程序 main() 的实现
package com.luobin.DataStructure.单链表;
import java.nio.charset.StandardCharsets;
/**
* @author LuoBin
* @version 1.0
* @date 2021/8/3 7:21 下午
*/
public class SingleLinkedListTest {
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, "林 冲", "豹子头");
HeroNode hero5 = new HeroNode(5, "张 三", "三 儿");
// 创建一个链表
SingleLinkedList singleLinkedList = new SingleLinkedList();
// // 进行加入
// // 此时的 add 没有考虑到相关的排进去排序的问题,顺序是可以乱的
// singleLinkedList.add(hero1);
// singleLinkedList.add(hero4);
// singleLinkedList.add(hero2);
// singleLinkedList.add(hero3);
// singleLinkedList.add(hero5);
// //显示
// singleLinkedList.list();
// 按照编号进行加入处理
System.out.println("按照编号进行添加的结果如下所示:\n");
singleLinkedList.addByOrder(hero1);
singleLinkedList.addByOrder(hero3);
singleLinkedList.addByOrder(hero5);
singleLinkedList.addByOrder(hero2);
singleLinkedList.addByOrder(hero4);
singleLinkedList.list();
}
}
2.5、对于链表的更新数据、删除节点
2.5.1、链表的更新
(1)实现思路
(2)实现代码
先找到该节点,通过遍历;
temp.name = newHeroNode.name ; temp.nickname= newHeroNode.nickname;
public void update(HeroNode newHeroNode) {
// 判断链表是否是空的
if (head.next == null) {
System.out.println("链表为空");
}
// 找到需要修改的节点,
// 定义辅助的变量,指向头节点后面的节点,因为头节点不是空的,向下面进行寻找
HeroNode temp = head.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 的节点,不能修改",newHeroNode.no);
}
}
(3)方法的调用
使用:类名.update(传入创建的节点对象)
2.5.2、链表的节点的删除
(1)实现思路
(2)实现代码
// 对于节点的删除操作
// hea的 保持不动,使用temp 进行辅助的操作,找到需要删除的前面一个节点
// 使用 temp.next.no 和需要删除的节点的比较
public void del(int no) {
HeroNode temp = head;
boolean flag =false; // 标志是否找到需要删除的节点
while (true) {
if (temp.next == null) { //到达链表的最后
break;
}
if (temp.next.no == no) { // 找到了需要删除的节点的前一个位置
flag = true; // 表示一下
break;
}
temp = temp.next;
}
// 判断 flag
if (flag) {
temp.next = temp.next.next;
} else {
System.out.println("没有找到需要删除的节点");
}
}
(3)方法的调用
使用:类名.del(传入需要删除的节点的号码)