// 正常插入链表(尾插法)
public void add(HeroNode heroNode) { //普通的插入结点的方法(俗称尾插法)。没有顺序,来一个往后插一个。
HeroNode temp = head; //头结点head不能动,所以需要一个辅助结点temp,且令它指向头结点
while(true) { //无限循环,但是可以用break;跳出。
if(temp.next == null) { //temp.next == null说明temp已经到链表的尾结点了,那么这个时候就可以直接跳出循环,把temp.next = heroNode;就完事了
break;
}else {
temp = temp.next; //来到这个分支,说明temp.next != null,也就是说temp还没有指到尾结点,那么这个时候就把temp向后移一位。
}
}
temp.next = heroNode; //执行条件:temp.next == null,temp来到尾结点,则直接接上要插入的节点就行。
}
// 按照编号顺序插入链表
//插入的思路是找到待添加结点的no的两个邻值a和b,有a <heroNode.no< b的关系,
// 但因为是单向链表,我们只能找到b,然后用temp去指向b的前一个结点a,再进行一系列操作
public void addByOrder(HeroNode heroNode) { //按照顺序添加结点,不是简单的尾插法了,按照编号排序
HeroNode temp = head; //同理,头结点head动不了,穿件一个辅助结点temp
boolean flag = false; //这里的flag是用来判断待添加结点的编号是不是在链表中已经存在 flag赋初值false,代表默认不存在,存在就添加不了了
while(true) { // 同样的无限循环,用break;即可跳出
if(temp.next == null) { //说明temp已经在链表的最后,也就是遍历完了,这时候再去看flag到底是true还是false,判断能不能插的进去。
break;
}
if(temp.next.no > heroNode.no) { //如果temp指向了b的前一个结点a的话,那么很好跳出循环就行了,再进行下一步操作。
break;
} else if (temp.next.no == heroNode.no) {//第一个if不满足且发现遍历的过程中出现了相同的编号(.no)的话,则把flag赋true,说明编号已经存在了。
flag = true; //编号存在
break;
}
temp = temp.next; //以上几个条件都不满足的话,说明还在遍历,没有找到“b”。
}
//跳出了循环,来看看flag。
if(flag) { //flag为true,说明编号已经存在,这时候就输出一句话,说编号已存在。
System.out.printf("准备插入的英雄的编号 %d 已经存在了, 不能加入\n", heroNode.no);
} else {
// 到这,说明成功找到了b,则准备插入。
heroNode.next = temp.next;
temp.next = heroNode;
}
}
//显示链表(遍历)
public void list() {
//先判断链表是否为空
if(head.next == null) { //头结点的下一个结点是null,说明整个链表除了头结点啥也没有,是一个空链表
System.out.println("链表为空");
return; // 链表为空,那输出错误信息之后直接return就行。
}
HeroNode temp = head.next; //跟add同理,头节点不能动,因此我们需要一个辅助变量来遍历。
while(true) {
if(temp == null) { // 因为while(true)循环,所以temp会一直后移到尾结点的下一个结点(也就是null)
break;
}
System.out.println(temp.no + temp.name); //输出结点的信息(也可改写toString()方法,但是暂时我还不会)
temp = temp.next;// 将temp后移,一定要后移,不然是个死循环!!!
}
}
//修改结点除no以外的信息(no不能改,改了就乱了)
//根据 newHeroNode 的 no 来修改即可(也就是说,实参newHeroNode的no就是待修改结点的no,根据这个找就行)
public void change(HeroNode newHeroNode) {
if(head.next == null) { //判断链表是否为空链表
System.out.println("链表为空~");
return;
}
//根据no编号找到需要修改的节点
HeroNode temp = head.next; //定义一个辅助变量
boolean flag = false; //flag表示是否已经找到该节点,false表示还没有找到要修改的节点,要是找到了就赋true
while(true) {
if (temp == null) { //说明已经遍历完链表(temp已经指到了尾结点的下一个。)
break;
}
if(temp.no == newHeroNode.no) { //说明找到了待修改的结点
flag = true; // flag赋true
break;
}
temp = temp.next; // 还没遍历完/没找到,后移temp。
}
if(flag) { // 根据flag判断是否已经找到要修改的节点
temp.name = newHeroNode.name; // 找到了 直接修改就行
temp.nickname = newHeroNode.nickname;
} else { //flag为false,说明没有找到
System.out.printf("没有找到 编号 %d 的节点,不能修改\n", newHeroNode.no);
}
}
// 删除节点的思路跟修改结点的思路是一样的,传待删除节点的编号(no)进去。然后利用辅助结点(temp)找到待删除结点,最后删除
//但是因为是单向链表,所以只能是tmep.next.no == no的时候,才进行删除操作。
public void delete(int no) { //删除结点
HeroNode temp = head; //头结点,老朋友了
boolean flag = false; // 标志是否已经找到待删除节点
while(true) {
if(temp.next == null) { //说明已经到链表的最后,可以直接跳出循环
break;
}
if(temp.next.no == no) {
//temp的下一个结点的编号等于no,再删除
flag = true;
break;
}
temp = temp.next; //temp后移,遍历链表
}
if(flag) { //flag为true,说明已经找到待删除节点
temp.next = temp.next.next; // 把待删除节点的下一个结点直接赋给待删结点的上一个节点,删除了待删除节点
}else { // flag为false,说明待删除节点不存在,输出错误信息。
System.out.printf("要删除的 %d 节点不存在\n", no);
}
}