public class DoubleLinkedListDemo {
public static void main(String[] args) {
System.out.println("双向链表的测试");
HeroNode2 hero1 = new HeroNode2(1, "宋江", "及时雨");
HeroNode2 hero2 = new HeroNode2(2, "卢金义", "玉麒麟");
HeroNode2 hero3 = new HeroNode2(3, "吴用", "智多星");
HeroNode2 hero4 = new HeroNode2(4, "林冲", "豹子头");
//创建一个双向链表对象
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
doubleLinkedList.add(hero1);
doubleLinkedList.add(hero2);
doubleLinkedList.add(hero3);
doubleLinkedList.add(hero4);
doubleLinkedList.list();
//修改
HeroNode2 hero5 = new HeroNode2(4, "公孙胜", "入云龙");
doubleLinkedList.update(hero5);
System.out.println("修改后的链表测试");
doubleLinkedList.list();
//删除
doubleLinkedList.delete(3);
System.out.println("删除后的链表情况");
doubleLinkedList.list();
}
static class DoubleLinkedList {
private HeroNode2 head = new HeroNode2(0, "", "");
public HeroNode2 getHead() {
return head;
}
/**
* 遍历显示链表
*/
public void list() {
if (head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode2 temp = head.next;
while (true) {
//判断链表是否到最后
if (temp == null) {
break;
}
System.out.println(temp);
temp = temp.next;
}
}
public void add(HeroNode2 heroNode) {
HeroNode2 temp = head;
while (true) {
if (temp.next == null) {
break;
}
temp = temp.next;
}
//形成一个双向链表,形成一个节点到双向链表的最后
temp.next = heroNode;
heroNode.pre = temp;
}
/**
* 第一个方法肯定是有序的添加数据,也可以叫插入
* 加入的是对象,即链表的一个部分
*/
public void addOrder(HeroNode2 heroNode) {
//1.我们需要一个辅助指针帮助遍历,让它成为头结点
HeroNode2 temp = head;
//2.需要标志flag来判断数据是否可添加
boolean flag = false;
//在将数据插入链表时,会有三种情况
//单纯的while-true 必须在每个条件下都加入break
while (true) {
//如果temp指向了null 说明链表已经到了尾部,直接退出循环
if (temp.next == null) {
break;
}
//如果temp指向的节点序号大于要插入的节点,说明找到了插入的位置
if (temp.next.num > heroNode.num) {
break;
}
//如果temp指向的节点序号等于要插入的节点,说明这个节点已经插入过
if (temp.next.num == heroNode.num) {
//那么此时我们将flag改成true,以便下文
flag = true;
break;
}
//如果三种情况都没发生,那么指针下移
temp = temp.next;
}
//如果是因为已经存在而终止循环,那么
if (flag) {
System.out.printf("已经存在%d", heroNode.num);
}
//如果是正常到了插入的位置,要进行链表独有的三方会转
else {
heroNode.next = temp.next;
temp.next = heroNode;
}
}
//链表的修改,修改一个节点的内容,和单向链表一样
public void update(HeroNode2 newHeroNode) {
if (head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode2 temp = head.next;
boolean flag = false;
while (true) {
if (temp == null) {
break;
}
if (temp.num == newHeroNode.num) {
flag = true;
break;
} else {
temp = temp.next;
}
}
if (flag) {
temp.nickname = newHeroNode.nickname;
temp.name = newHeroNode.name;
} else {
System.out.println("没有扎到");
}
}
/**
* 添加之后是删除,这里定义的就肯定不是你想删除的对象了
* 而是你想删除对象的序号即可,即以属性代表目标
* 对于双向链表,可以直接找到要删除的节点,而不是前一个节点
* 找到后自我删除即可
*/
public void delete(int num) {
//判断当前链表是否为空
if (head.next == null) {
System.out.println("链表为空,无法删除");
return;
}
//1.定义一个辅助指针
HeroNode2 temp = head.next;
//2.定义标志flag判断数据是否可添加
boolean flag = false;
while (true) {
//已经到了链表的最后节点的next
if (temp == null) {
break;
}
//找到带删除结点的前一个节点,只有这一个条件是正确的
if (temp.num == num) {
flag = true;
break;
}
//后移,遍历
temp = temp.next;
}
//找到了这个节点
if (flag) {
//temp.next = temp.next.next;
temp.pre.next = temp.next;
//代码有风险,如果temp是最后一个节点,会出现空指针异常
if (temp.next != null) {
temp.next.pre = temp.pre;
}
} else {
System.out.printf("要删除的%d节点不存在", num);
}
}
}
/**
* 这是一个链表类,每个HeroNode就是一个节点
* 在这里需要定义我们需要的链表的一些属性
* 比如此链表定义了num,name,nickname
* 当然最重要的是定义指向下一个节点的next
*/
static class HeroNode2 {
public int num;
public String name;
public String nickname;
public HeroNode2 next;
public HeroNode2 pre;
/**
* 链表类的第一个方法当然是创建链表,这里显然利用构造方法
* 对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。
*/
public HeroNode2(int num, String name, String nickname) {
this.num = num;
this.name = name;
this.nickname = nickname;
}
/**
* 接着重写一个toString方法,目的是返回对象的内容
*/
@Override
public String toString() {
return "HeroNode{" +
"num=" + num +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
}