package com.xu1.singleList;
/**
* @author xu
* @Description
* @date 2022/09/09 - 19:29:48
* @Modified By:
*/
public class SingleLinkedList {
//测试主函数
public static void main(String[] args) {
HeroNode heroNode2 = new HeroNode(2,"卢俊义","玉麒麟");
HeroNode HeroNode = new HeroNode(1,"宋江","及时雨");
HeroNode heroNode3 = new HeroNode(3,"吴用","智多星");
HeroNode heroNode5 = new HeroNode(5,"周瑜","羽扇纶巾");
HeroNode heroNode4 = new HeroNode(4,"武松","孙行者");
Operate_List operate_List = new Operate_List();
//为链表中增加对象
// operate_List.add(HeroNode);
// operate_List.add(heroNode2);
// operate_List.add(heroNode3);
//按照排名进行插入
operate_List.addByOrder(HeroNode);
operate_List.addByOrder(heroNode4);
operate_List.addByOrder(heroNode2);
operate_List.addByOrder(heroNode5);
operate_List.addByOrder(heroNode3);
//修改节点测试
HeroNode heroNode5_1 = new HeroNode(5,"鲁肃","羽扇纶巾");
operate_List.update(heroNode5_1);
//删除节点测试
operate_List.delect(3);
operate_List.list();
}
}
/**
*
* @Description
* 1.定义一个HeroNode类:
* @param
* @Author xu
* @Date 2022/09/09 19:58:02
*
*/
class HeroNode{
// 1-1:4个域:int number,String name,String nackname,HeroNode next
int number;
String name;
String nackname;
HeroNode next;
public HeroNode() {
super();
}
public HeroNode(int number, String name, String nackname) {
super();
this.number = number;
this.name = name;
this.nackname = nackname;
}
//1-2:重写toString方法
@Override
public String toString() {
return "HeroNode [number=" + number + ", name=" + name + ", nackname=" + nackname + "]";
}
}
/**
*
* @Description
* 2.定义一个Operate_List类:
* @param
* @Author xu
* @Date 2022/09/09 19:52:01
*
*/
class Operate_List{
//初始化一个头结点
HeroNode head = new HeroNode(0,"","");
/**
* 2-1 add():用于在链表的头部进行节点的插入
* 返回值:void;传入参数:HeroNode类型的对象
* 内部处理:
* 用一个while循环找到最后一个节点,
* 并将所传对象赋值给最后一个节点的下一个节点。
*/
public void add(HeroNode heroNode) {
//将头结点赋值给一个临时变量,从第一个开始遍历,找到最后一个节点
HeroNode temp = head;
while(temp.next != null) {
temp = temp.next;
}
temp.next = heroNode;
}
/**
* 2-2 list():
* 返回值:void 传入参数:HeroNode head
* 将头结点赋值给临时变量,
* 增加一个判断,如果链表为空,则没必要查找,
* 利用while之前,需用if对链表是否为空进行判断,并且作为遍历链表结束的条件,循环遍历链表,将其输出
*/
public void list() {
HeroNode temp = head;
//增加一个判断,如果链表为空,则没必要查找
if (temp.next == null) {
System.out.println("the list is empty!");
return;
}
while(true) {
if (temp.next == null) {
break;
}
//为了不将头结点输出
System.out.println(temp.next);
temp = temp.next;
}
}
/**
*
* @Description 链表按顺序插入,也就死说按照水浒传英雄排名进行插入
* @param
* @Author xu
* @Date 2022/09/09 20:17:16
*
*/
public void addByOrder(HeroNode heroNode) {
/**
* 需求:链表按顺序插入
* 思考:
* 首先,因为链表表头head不能改变,并且利于遍历对象的方便,需要设置一个临时对象temp,
* 其次,需要设置一个布尔类型的变量用于检验插入人物的编号是否已经存在,
* 用一个while循环遍历链表中的对象找到temp,
* 分三种情况:
* 插入元素等于所找元素的下一个元素temp.next找到需要插入的位置,插入元素大于所找元素的下一个元素temp.next,插入元素小于所找元素的下一个元素temp.next,
* 当小于时,即找到所找temp,将对象插入到temp下一个元素即可
*
* 设计:
* 1.设置一个临时对象temp,类型为:HeroNode,赋值为head,在此之前需要对head对象进行初始化
* 2.检验插入人物的编号是否已经存在:类型:boolean
* 3.while循环遍历链表中的对象找到所需temp
* 注意:以下顺序不能改变,应该是先判断下一个元素为空,再看元素能否进行插入,不能,再看元素是否相等,再将指针指向下一个对象
* 3-1:temp.next元素为空,说明没办法进行插入
* 3-2:插入元素小于所找元素的下一个元素temp.next,当小于时,即找到所找temp,将对象插入到temp下一个元素即可
* 3-3:插入元素等于所找元素的下一个元素temp.next,跳出去,并说明插入元素;已经存在
* 3-4:将指针指向下一个对象
* 4.当等于时,输出一句提示''已经存在元素,无法插入''
* 5.当小于时,heroNode.next = temp.next;temp.next = heroNode;注意该两条语句顺序不能颠倒
*/
//1.设置一个临时对象temp
HeroNode temp = head;
//2.检验插入人物的编号是否已经存在:类型:boolean
//为什么要设置为false
Boolean check_no = false;
//3.while循环遍历链表中的对象找到所需temp
while(true) {
//3-1:temp.next元素为空,说明没办法进行插入
if (temp.next == null) {
break;
}
//:3-2:插入元素小于所找元素的下一个元素temp.next,当小于时,即找到所找temp,将对象插入到temp下一个元素即可
else if(heroNode.number < temp.next.number) {
break;
}
//3-3插入元素等于所找元素的下一个元素temp.next,跳出去,并说明插入元素;已经存在(同一个排名不存在两个不同的人)
else if (heroNode.number == temp.next.number){
check_no = true;
break;
}
//3-4:将指针指向下一个对象
else {
temp = temp.next;
}
}
if (check_no) {
System.out.printf("已经存在元素%d,无法插入\n",heroNode.number);
}
else {
heroNode.next = temp.next;
temp.next = heroNode;
}
}
//需改节点-用no来找到所需修改的对象
/**
* 1.明确方法:返回 void,传入参数为:HeroNode类型的节点对象
* 2.因为头结点不能修改,所以需将头结点初始化,并赋值给HeroNode变量temp
* 补充:还需一个boolean变量flag=false,用于判断是否找到所要修改的节点
* 3.分三步走:
* 运用while循环,循环条件是true
* 3-1:如果下一个节点为空,退出循环
* 3-2:如果链表中对象的no与所传入的对象no相等,则可通过所传入对象完成对列表中对象的修改
* 3-2:将对象累加
* 4.
* 4-1:为空跳出循环后,输出一句,找不到对象
* 4-2:找到,对其进行赋值
*
*/
//1.明确方法:返回 void,传入参数为:HeroNode类型的节点对象
public void update(HeroNode newHeroNode) {
//2.因为头结点不能修改,所以需将头结点初始化,并赋值给HeroNode变量temp
HeroNode temp = head;
//补充:还需一个boolean变量flag=false,用于判断是否找到所要修改的节点
boolean flag = false;
//3.分三步走:
//运用while循环,循环条件是true
while(true) {
//3-1:如果下一个节点为空,退出循环
if (temp.next == null) {
break;//如果用return;直接跳出方法,下面语句不会输出
}
else if(newHeroNode.number == temp.number){
// 3-2:如果链表中对象的no与所传入的对象no相等,则可通过所传入对象完成对列表中对象的修改
flag = true;
break;
}
else {
//3-2:将对象累加
temp = temp.next;
}
}
//4-1:为空跳出循环后,输出一句,找不到对象
if(flag) {
System.out.printf("I can't find %d ",newHeroNode.number);
return;
}else {
//4-2:找到,对其进行赋值
temp.name = newHeroNode.name;
temp.nackname = newHeroNode.nackname;
}
}
/**
*
* @Description
* 单链表的删除
* @param
* @Author xu
* @Date 2022/09/09 21:12:13
*
*/
public void delect(int number) {
//建立一个临时变量指向头结点
HeroNode temp = this.head;
boolean flag;
//用于遍历每一个节点,找到需要删除的排名的节点
for(flag = false; temp.next != null; temp = temp.next) {
if (temp.next.number == number) {
flag = true;
break;
}
}
if (flag) {
temp.next = temp.next.next;
} else {
System.out.printf("i can't find %d", number);
}
}
}
结果:
HeroNode [number=1, name=宋江, nackname=及时雨]
HeroNode [number=2, name=卢俊义, nackname=玉麒麟]
HeroNode [number=4, name=武松, nackname=孙行者]
HeroNode [number=5, name=鲁肃, nackname=羽扇纶巾]