双向链表的基本原理和实现(Java)
程序员文章站
2024-02-05 12:09:10
...
双向链表基本原理:
双向链表也是链表的一种,它每个数据结点中都有两个结点,分别指向其直接前驱和直接后继。所以我们从双向链表的任意一个结点开始都可以很方便的访问其前驱元素和后继元素。
双向链表的结构如下图所示:
双向链表的基本操作:
分析 双向链表的遍历,添加,修改,删除的操作思路
- 遍历:和单链表一样,只是可以向前,也可以向后查找
- 添加 (默认添加到双向链表的最后):
(1) 先找到双向链表的最后这个节点
(2) temp.next = newHeroNode
(3) newHeroNode.pre = temp; - 修改:思路和原来的单向链表一样.
- 删除:
(1) 因为是双向链表,因此,我们可以实现自我删除某个节点
(2) 直接找到要删除的这个节点,比如temp
(3) temp.pre.next = temp.next
(4) temp.next.pre = temp.pre;
代码实现:
package LinkedList;
public class DoubleLinkListDemo {
public static void main(String[] args) {
System.out.println("双向链表的测试");
// 先创建节点
HeroNod hero1 = new HeroNod(1, "宋江", "及时雨");
HeroNod hero2 = new HeroNod(2, "卢俊义", "玉麒麟");
HeroNod hero3 = new HeroNod(3, "吴用", "智多星");
HeroNod hero4 = new HeroNod(4, "林冲", "豹子头");
// 创建一个双向链表
DoubleLinkList doubleLinkList = new DoubleLinkList();
doubleLinkList.add(hero1);
doubleLinkList.add(hero2);
doubleLinkList.add(hero3);
doubleLinkList.add(hero4);
System.out.println("修改前");
doubleLinkList.list();
HeroNod newHeroNode = new HeroNod(4, "公孙胜", "入云龙");
doubleLinkList.update(newHeroNode);
System.out.println("修改后");
doubleLinkList.list();
HeroNod new2HeroNode = new HeroNod(2, "卢俊义", "玉麒麟");
doubleLinkList.delete(new2HeroNode);
System.out.println("删除后");
doubleLinkList.list();
}
}
class DoubleLinkList {
private HeroNod head = new HeroNod(0, "", "");
// 向list中添加节点
public HeroNod getHead() {
return head;
}
// 遍历双向链表
public void list() {
if (head.next == null) {
System.out.println("该链表为空,无法遍历");
return;
}
HeroNod temp = head.next;
while (true) {
if (temp == null)
break;
System.out.println(temp);
temp = temp.next;
}
}
// 向双向链表中
public void add(HeroNod heronode) {
HeroNod temp = head;
while (true) {
if (temp.next == null)// 链表的辅助变量temp指向链表的最后一个元素
break;
temp = temp.next;
}
temp.next = heronode;
heronode.pre = temp;
}
// 修改双向链表中指定的值
public void update(HeroNod heronode) {
if (head.next == null) {
System.out.println("双向链表为空,无法修改指定元素");
return;
}
HeroNod temp = head.next;
boolean flag = false;
while (true) {
// 已遍历到链表的终点
if (temp == null) {
break;
}
// 找到要修改的no
if (temp.no == heronode.no) {
flag = true;
break;
}
// 跳转到下一个节点
temp = temp.next;
}
if (flag == false) {
System.out.println("链表中不存在要修改的元素的no");
return;
} else {
temp.name = heronode.name;
temp.nickName = heronode.nickName;
}
}
// 删除指定节点
public void delete(HeroNod heronode) {
HeroNod temp = head.next;
boolean flag = false;
while (true) {
if (temp == null)
break;
if (temp.no == heronode.no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag == true) {
temp.pre.next = temp.next;
temp.next.pre = temp.pre;
} else {
System.out.println("链表中不存在要删除的元素的no");
return;
}
}
}
class HeroNod {
public int no;
public String name;
public String nickName;
public HeroNod next;
public HeroNod pre;
public HeroNod(int no, String name, String nickName) {
super();
this.no = no;
this.name = name;
this.nickName = nickName;
}
@Override
public String toString() {
return "HeroNode [no=" + no + ", name=" + name + ", nickName=" + nickName + "]";
}
}
输出:
双向链表的测试
修改前
HeroNode [no=1, name=宋江, nickName=及时雨]
HeroNode [no=2, name=卢俊义, nickName=玉麒麟]
HeroNode [no=3, name=吴用, nickName=智多星]
HeroNode [no=4, name=林冲, nickName=豹子头]
修改后
HeroNode [no=1, name=宋江, nickName=及时雨]
HeroNode [no=2, name=卢俊义, nickName=玉麒麟]
HeroNode [no=3, name=吴用, nickName=智多星]
HeroNode [no=4, name=公孙胜, nickName=入云龙]
删除后
HeroNode [no=1, name=宋江, nickName=及时雨]
HeroNode [no=3, name=吴用, nickName=智多星]
HeroNode [no=4, name=公孙胜, nickName=入云龙]
为何要引入双向链表:
1、单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。
2、单向链表不能自我删除,需要靠辅助节点 ,而双向链表,则可以自我删除,所以前面我们单链表删除时节点,总是找到temp,temp是待删除节点的前一个节点。
上一篇: Base64编解码及其C++实现
下一篇: vue滑动进度条组件,可点击、可拖拽
推荐阅读
-
双向链表的基本原理和实现(Java)
-
定义两个接口,其中各包括一个抽象方法分别用来完成两个数的加法和减法操作,然后创建一个类KY6_3来实现这两个接口中的抽象方法。编写程序KY6_3.java,将源程序写在实验报告中。
-
Java swing 带界面和进度条的多线程下载器实现
-
Java实现Kafka的生产者和消费者例子
-
【Java基础】Annotation 的本质和自定义实现
-
数据结构(栈和队列的链表方式实现)
-
C语言实现双向非循环链表(不带头结点)的清空
-
数据结构---带头结点的双向链表的增删查改1(C语言实现)
-
Java 获取当前类名和方法名的实现方法
-
java中线程实现方式(execute和submit方式的区别)