双向链表
双向链表
双向链表的增删查改
背景
-
数据结构——双向链表
-
博主以b站尚硅谷Java数据结构与算法课进行学习
概念
-
双向链表遍历方法与单向链表相同,不过双向链表可以向前和向后查找
-
添加,默认添加到最后
- 先找到双向链表的最后节点
- temp.next = newHeroNode
- newHeroNode.pre = temp
-
修改,与单链表相同
-
删除
- 双向链表可以自我删除
- 直接找到要删除的节点temp
- temp.pre.next = temp.next
- temp.next.pre = temp.pre
问题
- 使用双向链表实现–水浒传排行榜管理
步骤
- 与单链表类似
代码实现
-
修改单链表中HeroNode类
-
增加pre变量指向链表中上一个节点
-
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23class HeroNode2 {
public int no;
public String name;
public String nickname;
public HeroNode2 next;//指向下个节点,默认为null
public HeroNode2 pre;//指向上个节点,默认为null
public HeroNode2(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
//为了显示方便,重写toString方法
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
-
-
遍历
-
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//遍历双向链表,与单链表一样
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;
}
}
-
-
添加
-
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public void add(HeroNode2 heroNode) {
//当不考虑编号顺序时
//先找到当前链表的最后节点
//将最后节点next指向新的节点
//因为head头节点不能动,所以需要辅助遍历temp
HeroNode2 temp = head;
//遍历链表找到最后
while (true) {
//代表找到链表的最后
if (temp.next == null) {
break;
}
//找不到就将temp后移,直至找到退出循环
temp = temp.next;
}
//当退出循环时,temp指向链表的最后
//形成双向链表
temp.next = heroNode;
heroNode.pre = temp;
}
-
-
修改
-
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29//修改双向链表节点
public void upadate(HeroNode2 newHeroNode) {
//判断链表是否为空
if (head.next == null) {
System.out.println("链表为空");
}
//找到需要修改的节点,根据no编号
//定义一个辅助变量temp
HeroNode2 temp = head.next;
boolean flag = false;//表示是否找到该节点
while (true) {
if (temp == null) {
break;//已经遍历完链表了
}
if (temp.no == newHeroNode.no) {
flag = true;//找到
break;
}
temp = temp.next;
}
// 根据flag判断是否找到要修改的节点
if (flag) {
temp.name = newHeroNode.name;
temp.nickname = newHeroNode.nickname;
} else {
//没有找到
System.out.println("没有找到");
}
}
-
-
删除
-
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29//从双向链表删除节点
//双向链表可以自我删除
public void del(int no){
//判断当前链表是否为空
if(head.next == null){{
System.out.println("链表为空,不能删除");
}
HeroNode2 temp = head.next;//辅助变量直接指向要删除的节点
boolean flag = false;//判断是否找到要删除节点的标志
while(true){
if(temp == null){
break;//到了链表最后
}
if(temp.no == no){//找到要删除的节点
flag = true;
break;
}
temp = temp.next;//后移
}if(flag){//找到执行
temp.pre.next = temp.next;
if (temp.next != null) {
temp.next.pre = temp.pre;//存在风险,如果是最后一个节点,不需要执行这段代码,否则会出现空指针异常
}
}
}else{//没有找到执行
System.out.printf("要删除的节点%d不存在\n",no);
}
}
-