根据编号no的值,删除双向链表的一个节点。
一、代码
package linkedlist;
/**
* 此双链表的头节点不是首节点
* @author Lee
*
*/
//一、 测试类
public class DoubleLinkedListDemo {
public static void main(String[] args) {
//1. 创建节点(英雄)
HeroNode2 hero1 = new HeroNode2(1, "宋江", "及时雨");
HeroNode2 hero2 = new HeroNode2(2, "卢俊义", "玉麒麟");
HeroNode2 hero3 = new HeroNode2(3, "吴用", "智多星");
HeroNode2 hero4 = new HeroNode2(4, "公孙胜", "入云龙");
HeroNode2 hero5 = new HeroNode2(5, "关胜", "大刀");
HeroNode2 hero6 = new HeroNode2(6, "林冲", "豹子头");
//2. 创建双链表
DoubleLinkedList doublelinkedlist1 = new DoubleLinkedList();
//3. 添加节点到双链表末尾并输出,输出顺序等于添加节点顺序
/*doublelinkedlist1.addByAdd(hero1);
doublelinkedlist1.addByAdd(hero3);
doublelinkedlist1.addByAdd(hero5);
doublelinkedlist1.addByAdd(hero2);
doublelinkedlist1.addByAdd(hero4);
doublelinkedlist1.addByAdd(hero6);
doublelinkedlist1.list();
*/
//4. 添加节点到双向链表(根据no的值),输出顺序等于no的顺序(可以理解为插入节点)
/*doublelinkedlist1.addByOrder(hero1);
doublelinkedlist1.addByOrder(hero6);
doublelinkedlist1.addByOrder(hero5);
doublelinkedlist1.addByOrder(hero2);
doublelinkedlist1.addByOrder(hero3);
doublelinkedlist1.addByOrder(hero4);
System.out.println("按编号顺序输出... ... ...");
doublelinkedlist1.list();
*/
//5.修改节点信息
/*doublelinkedlist1.addByAdd(hero1);
doublelinkedlist1.addByAdd(hero2);
System.out.println("修改节点信息之前... ... ...");
doublelinkedlist1.list();
System.out.println("----------双向链表中存在待修改的节点----------");
HeroNode2 newHeroNode1 = new HeroNode2(2, "吴用", "智多星");
doublelinkedlist1.update(newHeroNode1);
System.out.println("修改节点信息之后... ... ...");
doublelinkedlist1.list();
System.out.println("----------双向链表中不存在待修改的节点----------");
HeroNode2 newHeroNode2 = new HeroNode2(3, "宋江", "及时雨");
doublelinkedlist1.update(newHeroNode2);
System.out.println("修改节点信息之后");
doublelinkedlist1.list();
*/
//6.删除节点
doublelinkedlist1.addByAdd(hero1);
doublelinkedlist1.addByAdd(hero2);
System.out.println("删除节点之前... ... ...");
doublelinkedlist1.list();
System.out.println("----------双向链表中存在待删除编号的节点----------");
doublelinkedlist1.del(2);
System.out.println("删除节点之后... ... ...");
doublelinkedlist1.list();
System.out.println("----------双向链表中不存在待删除编号的节点");
doublelinkedlist1.del(2);
System.out.println("删除节点之后... ... ...");
doublelinkedlist1.list();
}
}
//二、 双链表类
class DoubleLinkedList{
// 初始化一个头节点,不存放具体数据,头节点不能动
private HeroNode2 head = new HeroNode2(0, "", "");
//1. 获得头节点
public HeroNode2 getHead() {
return head;
}
//2. 添加节点到双链表的最后,输出顺序等于添加顺序
//思路:直接将新节点添加到双链表的最后
//(1) 用 while 遍历链表,找到双链表的最后一个节点。当退出 while 时,辅助节点 temp 已指向双链表的最后一个节点(只要内存还有空间,理论上链表就不会满)
//(2) 直接将新节点接到双链表最后一个节点之后
public void addByAdd(HeroNode2 heronode) {
//(1) 遍历链表,找到双链表的最后一个节点
HeroNode2 temp = head;
while(true) {//对于不知道循环次数的情况,要用 while 循环
if(temp.next == null) {
break;
}
temp = temp.next;//temp 后移,继续遍历双链表
}
//(2) 当退出 while循环时,temp就指向了双链表的最后一个节点
temp.next = heronode;
heronode.pre = temp;//这里一定要注意,不能丢掉,否则就不是双链表
}
//3. 添加节点到双链表,根据 no 的值添加,输出顺序等于编号顺序(可以理解为插入节点)
public void addByOrder(HeroNode2 heronode) {
//(1) 遍历链表,找到待加入点的前一个节点
HeroNode2 temp = head;//temp指向待添加节点的前一个位置,所以temp的值为head,而不是head.next
boolean flag = false;//表示双链表中是否已存在待加入的节点,默认 false ,不存在
while(true) {
//<1> temp已经指向双链表最后一个节点,退出循环
if(temp.next == null) {
break;
}
//<2> temp没有指向双链表最后一个节点,让temp指向待加入节点的前一个节点
if(temp.next.no > heronode.no) {
break;
}else if(temp.next.no == heronode.no) {
flag = true;
break;
}
//<3> 上面的情况都没有出现,temp后移,继续遍历
temp = temp.next;
}
//(2) 判断flag的值,检查待添加的节点是否存在
if(flag) {//待添加的节点已存在
System.out.println("待添加的节点已存在... ... ...");
}else if(temp.next != null){//待添加的节点不存在,且temp不是指向双链表的最后一个节点
HeroNode2 temp1 = temp.next;
heronode.pre = temp;
heronode.next = temp1;
temp1.pre = heronode;
temp.next = heronode;
}else {//待添加的节点不存在,且temp指向双链表的最后一个节点
heronode.pre = temp;
heronode.next = null;
temp.next = heronode;
}
}
//4. 显示/输出链表(遍历),按no的大小顺序输出
public void list() {
//(1) 首先判断双链表是否为空
if(head.next == null) {
System.out.println("双链表为空... ... ...");
return;//结束方法,不能丢掉
}
//(2) 双链表非空,继续输出
HeroNode2 temp = head.next;
while(true) {
//<1> 首先判断temp是否指向双链表最后一个节点的后一个节点
if(temp == null) {
break;
}
//<2> temp没有指向双链表最后一个节点的后一个节点,继续遍历输出
System.out.println(temp);
temp = temp.next;
}
}
//5. 修改节点信息,根据 no 的值(和单向链表相同)
public void update(HeroNode2 heronode) {
//(1) 首先判断双链表是否为空
if(head.next == null) {
System.out.println("双链表为空... ... ...");
return;//结束方法,不能丢掉
}
//(2) 双链表非空,继续遍历双链表,找到待修改的节点
HeroNode2 temp = head.next;
boolean flag = false;//表示是否找到待修改的节点,默认为 false ,没找到
while(true) {
//<1> 首先判断是否到达双链表最后
if(temp == null) {//已经遍历完链表。如果此处用temp.next == null,则无法修改最后一个节点
break;
}
//<2> 没有到达双链表最后,继续遍历,直到找到待修改节点。找到后,退出 while 循环
if(temp.no == heronode.no) {
flag = true;
break;
}
//<3> 没有找到待修改的节点,继续遍历双链表
temp = temp.next;
}
//(3) 判断 flag 的值,决定是否能成功修改节点信息
if(flag) {
temp.name = heronode.name;
temp.nickname = heronode.nickname;
}else {
System.out.println("待修改的节点不存在... ... ...");
}
}
//6. 删除一个节点,根据 no 的值(双链表可以自我删除)
//思路:双链表可以自我删除,所以只需要找到待删除的节点即可
public void del(int no) {
//(1) 首先判断双链表是否为空
if(head.next == null) {
System.out.println("双链表为空... ... ...");
return;//结束方法
}
//(2) 双链表不为空,遍历双链表,直到找到待删除的节点
HeroNode2 temp = head.next;//辅助节点
boolean flag = false;//表示是否找到待删除的节点,默认为 false ,没找到
while(true) {
//<1> 首先判断 temp 是否指向双链表的最后一个节点
if(temp == null) {//由于双向链表的节点可以自我删除,所以此处不能用temp.next == null。如果用temp.next == null,会导致最后一个节点无法删除。
break;
}
//<2> temp没有指向双链表的最后一个节点,继续遍历双链表,直到找到待删除的节点
if(temp.no == no) {
flag = true;
break;
}
//<3> temp没有指向双链表的最后一个节点,且没有找到待删除的节点,继续遍历双链表
temp = temp.next;
}
//(3) 判断 flag 的值,决定是否删除节点
if(flag) {//找到了待删除的节点
temp.pre.next = temp.next;//将待删除节点的前一个节点的后驱改成待删除节点的后一个节点
if(temp.next != null) {
//注意:如果待删除节点是双向链表的最后一个节点,即temp.next == null,不需要执行下面的语句,否则会出现空指针
temp.next.pre = temp.pre;//将待删除节点的后一个节点的前驱改成待删除节点的前一个节点
}
}else {
System.out.println("没有找到待删除的节点... ... ...");
}
}
}
//三、 双链表节点类
class HeroNode2{
public int no;
public String name;
public String nickname;
public HeroNode2 pre;//指向前一个节点,默认为 null
public HeroNode2 next;//指向后一个节点,默认为 null
// 构造方法
public HeroNode2(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
// 为了显示方便,重写 toString 方法
@Override
public String toString() {
return "HeroNode2 [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
}
}
二、结果
删除节点之前... ... ...
HeroNode2 [no=1, name=宋江, nickname=及时雨]
HeroNode2 [no=2, name=卢俊义, nickname=玉麒麟]
----------双向链表中存在待删除编号的节点----------
删除节点之后... ... ...
HeroNode2 [no=1, name=宋江, nickname=及时雨]
----------双向链表中不存在待删除编号的节点
没有找到待删除的节点... ... ...
删除节点之后... ... ...
HeroNode2 [no=1, name=宋江, nickname=及时雨]