什么是链表
- 链表是以节点的方式用来存储数据的,是链式存储
- 每个节点分为两个区域:data域和next域;next域是指向下一个节点的。
- 同时链表分为带头节点和不带头结点的链表
- 链表的各个节点不一定是连续存储的
链表的实现
需求
创建一个带头节点的单链表,用来存储英雄的信息(排名编号、姓名、昵称),并可以实现增删改查的操作
分析及实现
- 首先创建一个HeroNode类,里面包含两个部分data:no,name,nickName)以及next节点
下面展示一些内联代码片
。
class HeroNode{
public int no;
public String name;
public String nickName;
HeroNode next;
public HeroNode(int no, String name, String nickName){
this.no = no;
this.name = name;
this.nickName = nickNmae;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickName='" + nickName + '\'' +
'}';
}
}
- 创建一个用来管理这些英雄的ManageHero类,在这个类中实现对英雄的增删改查等操作
添加
方式一:直接将新英雄添加到链表的最后
class ManageHero{
// 初始化头结点
HeroNode head = new HeroNode(0, "", "");
/**
* 添加英雄
* 方式1:直接将新英雄添加到链表的最后
* @param heroNode 传入新创建的英雄
*/
public void addHero(HeroNode heroNode){
// 将节点添加到最后首先需要遍历链表到最后一个节点
// 头结点不能移动 所以定义一个辅助变量来帮助遍历
HeroNode temp = head;
while(true){
if(temp.next == null){// 当最后一个节点的next为null时 则说明到了最后一个节点处
break;
}
// 将辅助节点依次后移
temp = temp.next;
}
// 当循环结束时 则已经遍历到最后一个节点
// 此时直接将新节点插入即可
temp.next = heroNode;
}
}
方式二:按照英雄的排名顺序添加
public void addByNo(HeroNode newHeroNode){
// 定义辅助变量
HeroNode temp = head;
// 定义一个标识来确定添加的编号是否重复
boolean flag = false;
while(true){
if(temp.next == null){
break;
}else if(temp.next.no > newHeroNode.no){// 若该节点的后一个节点no大于新节点的no 那么该节点为需要替换的位置
break;
}else if(temp.next.no == newHeroNode.no){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
System.out.printf("编号%d已存在,无法添加!",newHeroNode.no);
}
newHeroNode.next = temp.next;
temp.next = newHeroNode;
}
运行结果:
查找
/**
* 按照编号查找英雄
* @param no 输入英雄编号
* @return 返回找到英雄或null
*/
public HeroNode findHero(int no){
if(head.next == null){
System.out.println("链表为空!");
}
HeroNode temp = head;
boolean flag = false;// 标识是否找到该编号的英雄
while(true){
if(temp == null){
break;
}else if(temp.no == no){
flag = true;
break;
}
temp = temp.next;
}
// 根据标识判断是否找到了
if(flag){
return temp;
}
System.out.printf("未找到编号为%d的英雄!\n",no);
return null;
}
修改
/**
* 修改英雄
* @param heroNode 传入已存在的英雄节点
*/
public void updateHero(HeroNode heroNode){
if(head.next == null){
System.out.println("链表为空!");
}
HeroNode temp = head.next;
boolean flag = false;
while(true){
if(temp == null){
break;
}else if(temp.no == heroNode.no){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
temp.name = heroNode.name;
temp.nickName = heroNode.nickName;
}
System.out.println("未找到" + heroNode.no + "号英雄!");
}
删除
删除示意图
/**
* 删除英雄
* 1. 单向链表所以需要找到 temp.next.no == no(输入的编号)
* 2. 此时 将temp = temp.next.next
* 3. 而temp.next则会被GC(垃圾回收机制)回收
* @param no 编号
*/
public void delHero(int no){
// 判断链表是否为空链表
if(head.next == null){
System.out.println("链表为空!");
}
HeroNode temp = head;
boolean flag = false;// 标识是否找到该编号的英雄
while(true){
if(temp.next == null){
break;
}else if(temp.next.no == no){
flag = true;
break;
}
temp = temp.next;
}
if(flag){
temp.next = temp.next.next;
}else{
System.out.println("未找到" + no + "号英雄!");
}
}
遍历链表
/**
* 打印单链表
*/
public void showList(){
// 判断链表是否为空链表
if(head.next == null){
System.out.println("链表为空!");
}
HeroNode temp = head.next;
while(true){
if(temp == null){// 当最后一个节点的next为null时 则说明到了最后一个节点处
break;
}
System.out.println(temp);
// 将辅助节点依次后移
temp = temp.next;
}