1. 目的:使用Java实现一个简单的链表
-
链表的存储对象为自定义Hero类的实例化;
-
定义链表的节点类HeroNode;
-
定义链表类SingleLinkedList;
-
链表类SingleLinkedList应具有如下几个方法:
- addHero( )方法:用来向链表中添加英雄;
- addHeroByIdASC( ):以ID作为标准升序添加英雄;
- dropHeroByID( )方法:通过ID删除英雄;
- updateHeroNameByID( ):通过ID修改英雄的名字;
- updateHeroNicknameByID( ):通过ID修改英雄昵称;
- updateHeroByID( ):通过ID修改英雄的名字与昵称;
- listAll( ):显示链表所有数据。
2.Hero类的实现
package 单链表;
/**
* @Classname Hero
* @Description TODO
* @Date 2022/4/10 13:02
* @Created by jiawen
*/
public class Hero {
String name;
String nikeName;
int id;
public Hero(String name, String nikeName, int id) {
this.name = name;
this.nikeName = nikeName;
this.id = id;
}
@Override
public String toString() {
return "Hero{" +
"name='" + name + '\'' +
", nikeName='" + nikeName + '\'' +
", id=" + id +
'}';
}
}
3.节点类HeroNode的实现
节点类包含两个基本属性:(1) hero属性,表示该节点的Hero数据;(2)HeroNode类型的nextHeroNode 属性,表示该链表节点的下一个数据。
这里修改了toString方法,增加了一个判断语句,这样可以解决在后面遍历链表时最后一个数据不会被显示的问题。
package 单链表;
/**
* @Classname HeroNode
* @Description TODO
* @Date 2022/4/10 13:03
* @Created by jiawen
*/
public class HeroNode {
Hero hero;
HeroNode nextHeroNode;
@Override
public String toString() {
if(this.nextHeroNode==null){
return "HeroNode{" +
"hero=" + hero +
", nextHeroNodeName=null"+
'}';
}
return "HeroNode{" +
"hero=" + hero +
", nextHeroNodeName=" + nextHeroNode.hero.name +
'}';
}
public HeroNode(Hero hero) {
this.hero = hero;
}
}
4.链表类的实现
链表默认有一个表头,所以需首先初始化一个头节点
package 单链表;
/**
* @Classname SingleLinkedList
* @Description TODO
* @Date 2022/4/10 13:08
* @Created by jiawen
*/
public class SingleLinkedList {
HeroNode headHeroNode = new HeroNode(new Hero("HEAD", "HEAD", -1));//头节点的初始化,参数可以随便填
/*
1:新节点的插入一定在表末尾,需要先找到末尾;
2:当指针所在节点上的下个节点属性为null,证明到了链表尾部,新节点的插入应该在指针后面;
3:找到则跳出while循环,否则指针后移;
4:一旦跳出了while循环,意味着指针在最后一个节点上,将这个节点的nextHeroNode属性赋值为新节点即可。
*/
public void addHero(HeroNode heroNode) {
HeroNode temp = headHeroNode;//定义一个指针temp,一开始指向头节点
while (true) {
if (temp.nextHeroNode == null) {
break;
}
temp = temp.nextHeroNode;
}
temp.nextHeroNode = heroNode;
}
/*依旧通过指针temp来遍历*/
public void listAll() {
if (headHeroNode.nextHeroNode == null) {
System.out.println("This list is is empty!");
return;
}
HeroNode temp = headHeroNode.nextHeroNode;
while (true) {
if (temp == null) {
break;
}else{
System.out.println(temp);
temp = temp.nextHeroNode;
}
}
}
public void addByIdASC(HeroNode heroNode) {
HeroNode temp = headHeroNode;
boolean flag = true;//这个flag很重要,它在添加节点ID与已有的节点ID重复时被取反
while (true) {
if (temp.nextHeroNode == null) {//这个判断必须要有,否则下面的if在ID重复时将会一直在while循环无法跳出
break;
}
if (temp.nextHeroNode.hero.id > heroNode.hero.id) {//如果指针的下一个id比待插入的要大,证明这个待插入的数据在指针后
break;
} else if (temp.nextHeroNode.hero.id == heroNode.hero.id) {//证明待插入数据的ID与已有的冲突,不允许插入,并将flag取反
flag = !flag;
break;
} else {//证明指针的下一个数据ID比待插入的要小,所以指针仍然需要后移
temp = temp.nextHeroNode;
}
}
/*
flag如果取反了,证明想要插入的数据已经存在,否则将数据插入,
注意更改顺序,应该先更改待插入数据的nextHeroNode,再更改待插入数据前面那个数据的nextHeroNode*/
if (!flag) {
System.out.println("The data ID which you are going to insert already exists");
} else {
heroNode.nextHeroNode = temp.nextHeroNode;
temp.nextHeroNode = heroNode;
}
}
//后面四个方法实现方式大同小异,重点是对temp指针的理解
public void updateHeroNameByID(int id, String udateName) {
if (headHeroNode.nextHeroNode == null) {
System.out.println("This list is empty!");
return;
}
HeroNode temp = headHeroNode.nextHeroNode;
boolean flag = false;
while (true) {
if (temp.nextHeroNode == null) {//这个判断条件大量出现,作用是防止当下面的if语句没有满足条件时,指针temp会不断向后,出现NullPointException
break; //这个if的作用就是确保在没有找到时程序可以正常跳出while循环
}
if (temp.hero.id == id) {
flag = !flag;
break;
} else {
temp = temp.nextHeroNode;
}
}
if (!flag) {
System.out.println("No hero found for ID = " + id);
} else {
temp.hero.name = udateName;
}
}
public void updateHeroNicknameByID(int id, String udateNickname) {
if (headHeroNode.nextHeroNode == null) {
System.out.println("This list is empty!");
return;
}
HeroNode temp = headHeroNode.nextHeroNode;
boolean flag = false;
while (true) {
if (temp.nextHeroNode == null) {//这个判断条件大量出现,作用是防止当下面的if语句没有满足条件时,指针temp会不断向后,出现NullPointException
break; //这个if的作用就是确保在没有找到时程序可以正常跳出while循环
}
if (temp.hero.id == id) {
flag = !flag;
break;
} else {
temp = temp.nextHeroNode;
}
}
if (!flag) {
System.out.println("No hero found for ID = " + id);
} else {
temp.hero.nikeName = udateNickname;
}
}
public void updateHeroByID(int id, String updateName, String udateNickname) {
if (headHeroNode.nextHeroNode == null) {
System.out.println("This list is empty!");
return;
}
HeroNode temp = headHeroNode.nextHeroNode;
boolean flag = false;
while (true) {
if (temp.nextHeroNode == null) {//这个判断条件大量出现,作用是防止当下面的if语句没有满足条件时,指针temp会不断向后,出现NullPointException
break; //这个if的作用就是确保在没有找到时程序可以正常跳出while循环
}
if (temp.hero.id == id) {
flag = !flag;
break;
} else {
temp = temp.nextHeroNode;
}
}
if (!flag) {
System.out.println("No hero found for ID = " + id);
} else {
temp.hero.name = updateName;
temp.hero.nikeName = udateNickname;
}
}
public void dropHeroByID(int id) {
if (headHeroNode.nextHeroNode == null) {
System.out.println("This list is empty!");
return;
}
HeroNode temp = headHeroNode;
boolean flag = false;
while (true) {
if (temp.nextHeroNode == null) {
break;
}
if (temp.nextHeroNode.hero.id == id) {
flag = !flag;
break;
} else {
temp = temp.nextHeroNode;
}
}
if (!flag) {
System.out.println("No hero found for ID = " + id);
} else {
temp.nextHeroNode = temp.nextHeroNode.nextHeroNode;
}
}
}
5.编写测试Demo测试代码
package 单链表;
/**
* @Classname Demo
* @Description TODO
* @Date 2022/4/10 13:42
* @Created by jiawe
*/
public class Demo {
public static void main(String[] args) {
HeroNode heroNode1 = new HeroNode(new Hero("关羽", "云长",1));
HeroNode heroNode2 = new HeroNode(new Hero("张飞", "翼德",2));
HeroNode heroNode3 = new HeroNode(new Hero("赵云", "子龙",3));
HeroNode heroNode4 = new HeroNode(new Hero("马超", "孟起",4));
HeroNode heroNode5 = new HeroNode(new Hero("黄忠", "汉升",5));
SingleLinkedList singleLinkedList = new SingleLinkedList();
singleLinkedList.addByIdASC(heroNode1);
singleLinkedList.addByIdASC(heroNode5);
singleLinkedList.addByIdASC(heroNode2);
singleLinkedList.addByIdASC(heroNode4);
singleLinkedList.addByIdASC(heroNode3);
//singleLinkedList.dropHeroByID(8);
//singleLinkedList.listAll();
//几种方法分别测试即可...
}
}