双向链表分析
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
双向链表分析
单向链表查找的方向只能是一个方向双向链表是可以向前或者向后查找的
单项链表不能自我删除但是双向链表是可以实现自我删除的
增删改查的思路分析
-
遍历方法和单链表是一样的不过双向链表可以向前也可以向后查找
-
添加(默认添加到双向链表的最后)
-
先找到双向链表的最后这个节点
-
temp.next=newHeroNode
-
newHeroNode.pre=temp
-
-
修改思路和单链表的原理一样
-
删除
-
因为是双向链表我们可以实现自我删除某个节点
-
直接找到要删除的节点比如temp
-
temp.pre.next=temp.next
-
temp.next.pre=temp.pre
-
代码实现
//定义HeroNode2每个HeroNode2对象就是一个节点
class HeroNode2 {
public int no;
public String name;
public String nickname;
public HeroNode2 next;// 指向下一个节点
public HeroNode2 pre;// 指向前一个节点
// 构造器
public HeroNode2(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "HeroNode2{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
// 创建一个双向链表的类
class DoubleLinkedList {
// 先初始化头节点
private HeroNode2 head = new HeroNode2(0, "", "");
// 返回头节点
public HeroNode2 getHead() {
return head;
}
}
添加
// 添加一个节点到双向链表的最后
public void add(HeroNode2 heroNode) {
// 因为head节点不能动 所以我们要声明一个变量帮助遍历
HeroNode2 temp = head;
// 遍历链表 找到最后
while (true) {
// 找到链表的最后
if (temp.next == null) {
break;
}
// 如果没有找到最后将cur后移
temp = temp.next;
}
// 当退出while循环时cur指向最后
//形成一个双向链表
temp.next = heroNode;
heroNode.pre = temp;
}
// 插入
public void insert(HeroNode2 heroNode) {
// 头节点不能动需要辅助变量
// 因为单链表我们找到的temp是位于添加位置的前一个节点否则插入不了
HeroNode2 temp = head;
boolean flag = false;// flag标志添加的编号已经存在 无法添加
while (true) {
if (temp.next == null) {// 说明temp已经在链表的最后了
break;
}
if (temp.next.no > heroNode.no) {// 说明已经找到了要插入的位置,就在temp后面插入
break;
} else if (temp.next.no == heroNode.no) {// 说明需要添加的节点点已经存在了
flag = true;// 说明编号存在
break;
}
temp = temp.next;
}
if (flag) {
System.out.println("编号已经存在 不能加入:" + heroNode.no);
} else {
// 插入到链表temp的后面
heroNode.next = temp.next;
// 防止空指针报错
if (temp.next != null) {
temp.next.pre = heroNode;
}
temp.next = heroNode;
heroNode.pre = temp;
}
}
删除
// 从双向链表中删除一个节点
/*
* 因为是双向链表我们可以实现自我删除某个节点
* 直接找到要删除的节点比如temp
* */
public void remove(int no) {
// 判断是否为空
if (head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode2 temp = head.next;
while (true) {
if (temp == null) {// 已经都链表的最后
break;
}
if (temp.no == no) {// 找到了要删除的节点的前一个节点
temp.pre.next = temp.next;
// 代码有问题
// 如果是最后一个节点就不需要执行下面这句话否则会报空指针异常
if (temp.next != null) {
temp.next.pre = temp.pre;
}
break;
}
temp = temp.next;
}
}
修改
// 修改一个节点内容可以看出双向链表的的修改节点内容和单向链表是一样的
public void update(HeroNode2 newHeroNode) {
if (head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode2 temp = head.next;
while (true) {
if (temp == null) {
break;// 已经遍历完链表
}
if (temp.no == newHeroNode.no) {
// 找到需要修改的节点
temp.name = newHeroNode.name;
temp.nickname = newHeroNode.nickname;
}
temp = temp.next;
}
}
遍历
// 显示链表[遍历]
public void show() {
// 判断链表是否为空
if (head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode2 cur = head.next;
while (true) {
if (cur == null) {
break;
}
// 输出节点信息
System.out.println(cur);
// 将cur后移否则会出现死循环
cur = cur.next;
}
}
测试方法和我们之前测试单链表的方式一样