数据结构之链表(LinkedList)(二)
数据结构之链表(LinkedList)(一)
双链表
上一篇讲述了单链表是通过next 指向下一个节点,那么双链表就是指不止可以顺序指向下一个节点,还可以通过prior域逆序指向上一个节点
示意图:

那么怎么来实现双链表的增删改查操作呢。
分析:
1) 遍历 方和 单链表一样,只是可以向前,也可以向后查找
2) 添加 (默认添加到双向链表的最后)
① 先找到双向链表的最后这个节点
② temp.next = newStuNode
③ newStuNode.prior = temp;
3) 修改 思路和 原来的单向链表一样.
4) 删除
①因为是双向链表,因此,我们可以实现自我删除某个节点
② 直接找到要删除的这个节点,比如temp
③ temp.prior.next = temp.next
④ temp.next.prior= temp.prior;
实现代码:
添加&遍历:
默认添加在链表最后一个。
// 添加一个节点到双向链表的最后.
public void add(StuNode2 stuNode2){ // 因为head节点不能动,因此我们需要一个辅助遍历 temp
StuNode2 temp = head;
// 遍历链表,找到最后
while (true) {
// 找到链表的最后
if (temp.next == null) {//
break;
}
// 如果没有找到最后, 将将temp后移
temp = temp.next;
}
// 当退出while循环时,temp就指向了链表的最后
// 形成一个双向链表
temp.next = stuNode2;
stuNode2.prior = temp;
}
添加代码
//遍历双向列表的方法 和单项列表一致
//显示链表[遍历]
public void list() {
//判断链表是否为空
if(head.next == null) {
System.out.println("链表为空");
return;
}
//因为头节点,不能动,因此我们需要一个辅助变量来遍历
StuNode2 temp = head.next;
while(true) {
//判断是否到链表最后
if(temp == null) {
break;
}
//输出节点的信息
System.out.println(temp);
//将temp后移, 一定小心
temp = temp.next;
}
}
遍历代码
public static void main(String[] args) {
//进行测试
//先创建节点
StuNode2 stu1 = new StuNode2(1, "张三", "85");
StuNode2 stu2 = new StuNode2(2, "李四", "87");
StuNode2 stu3 = new StuNode2(3, "小明", "70");
StuNode2 stu4 = new StuNode2(4, "小红", "90");
//创建要给链表
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
//加入
doubleLinkedList.add(stu1);
doubleLinkedList.add(stu2);
doubleLinkedList.add(stu3);
doubleLinkedList.add(stu4);
System.out.println("原始双链表数据 " );
doubleLinkedList.list();;
}
main
原始双链表数据
StuNode [stuNo=1, name=张三, mark=85]
StuNode [stuNo=2, name=李四, mark=87]
StuNode [stuNo=3, name=小明, mark=70]
StuNode [stuNo=4, name=小红, mark=90]
输出
根据序号排序添加
上面添加是默认添加到最后一个节点,那么要求根据序号默认排序添加呢,其实和单链表是一样思路
public void addByOrder(StuNode2 stuNode2){
StuNode2 temp = head;
boolean flag = false;
while (true){
if (temp.next == null){
break;
}
if (temp.next.stuNo>stuNode2.stuNo){//位置找到
break;
}else if (temp.stuNo == stuNode2.stuNo){
flag=true;
break;
}
temp =temp.next;
}
if (flag){
System.out.printf("准备插入的学生 %d 已经存在了, 不能加入\n", stuNode2.stuNo);
}else{
stuNode2.next=temp.next;
temp.next=stuNode2;
stuNode2.prior=temp;
if(temp.next != null){
temp.next.prior=stuNode2;
}
}
}
代码
修改:
// 修改一个节点的内容, 可以看到双向链表的节点内容修改和单向链表一样
// 只是 节点类型改成 StuNode2
public void update(StuNode2 newStuNode) {
// 判断是否空
if (head.next == null) {
System.out.println("链表为空~");
return;
}
// 找到需要修改的节点, 根据stuNo编号
// 定义一个辅助变量
StuNode2 temp = head.next;
boolean flag = false; // 表示是否找到该节点
while (true) {
if (temp == null) {
break; // 已经遍历完链表
}
if (temp.stuNo == newStuNode.stuNo) {
// 找到
flag = true;
break;
}
temp = temp.next;
}
// 根据flag 判断是否找到要修改的节点
if (flag) {
temp.name = newStuNode.name;
temp.mark = newStuNode.mark;
} else { // 没有找到
System.out.printf("没有找到 学号 %d 的节点,不能修改\n", newStuNode.stuNo);
}
}
修改代码
public static void main(String[] args) {
//进行测试
//先创建节点
StuNode2 stu1 = new StuNode2(1, "张三", "85");
StuNode2 stu2 = new StuNode2(2, "李四", "87");
StuNode2 stu3 = new StuNode2(3, "小明", "70");
StuNode2 stu4 = new StuNode2(4, "小红", "90");
//创建要给链表
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
//加入
doubleLinkedList.add(stu1);
doubleLinkedList.add(stu2);
doubleLinkedList.add(stu3);
doubleLinkedList.add(stu4);
System.out.println("原始双链表数据 " );
doubleLinkedList.list();;
//修改3号的分数
StuNode2 stu = new StuNode2(3,"小明","99");
doubleLinkedList.update(stu);
System.out.println("修改后的链表");
doubleLinkedList.list();;
}
main
原始双链表数据
StuNode [stuNo=1, name=张三, mark=85]
StuNode [stuNo=2, name=李四, mark=87]
StuNode [stuNo=3, name=小明, mark=70]
StuNode [stuNo=4, name=小红, mark=90]
修改后的链表
StuNode [stuNo=1, name=张三, mark=85]
StuNode [stuNo=2, name=李四, mark=87]
StuNode [stuNo=3, name=小明, mark=99]
StuNode [stuNo=4, name=小红, mark=90]
输出
删除:
上篇单链表的思路是找到要删除节点的前一个节点,然后待删除节点的前一个节点直接指向待删除节点的后一个节点,隐藏待删除的节点,从而达到删除目的。
那么双链表可以直接找到待删除节点temp,通过逆指向 temp.prior 找到待删除节点的上一个节点,然后顺指向temp.prior.next 指向待删除节点的下一个节点temp.next
也就是 temp.prior.next = temp.next。同时要修改 待删除节点的下一个节点的逆指向 指向待删除节点的上一个节点,也就是temp.next.prior= temp.prior;
示意图:

// 从双向链表中删除一个节点,
// 说明
// 1 对于双向链表,我们可以直接找到要删除的这个节点
// 2 找到后,自我删除即可
public void del(int stuNo) { // 判断当前链表是否为空
if (head.next == null) {// 空链表
System.out.println("链表为空,无法删除");
return;
} StuNode2 temp = head.next; // 辅助变量(指针)
boolean flag = false; // 标志是否找到待删除节点的
while (true) {
if (temp == null) { // 已经到链表的最后
break;
}
if (temp.stuNo == stuNo) {
// 找到的待删除节点的前一个节点temp
flag = true;
break;
}
temp = temp.next; // temp后移,遍历
}
// 判断flag
if (flag) { // 找到
// 可以删除
// temp.next = temp.next.next;[单向链表]
temp.prior.next = temp.next;
// 如果是最后一个节点,就不需要执行下面这句话,否则出现空指针
if (temp.next != null) {
temp.next.prior = temp.prior;
}
} else {
System.out.printf("要删除的 %d 节点不存在\n", stuNo);
}
}
删除代码
public static void main(String[] args) {
//进行测试
//先创建节点
StuNode2 stu1 = new StuNode2(1, "张三", "85");
StuNode2 stu2 = new StuNode2(2, "李四", "87");
StuNode2 stu3 = new StuNode2(3, "小明", "70");
StuNode2 stu4 = new StuNode2(4, "小红", "90");
//创建要给链表
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
//加入
doubleLinkedList.add(stu1);
doubleLinkedList.add(stu2);
doubleLinkedList.add(stu3);
doubleLinkedList.add(stu4);
System.out.println("原始双链表数据 " );
doubleLinkedList.list();
//删除3号数据
doubleLinkedList.del(3);
System.out.println("删除后的链表 " );
doubleLinkedList.list();
}
main
原始双链表数据
StuNode [stuNo=1, name=张三, mark=85]
StuNode [stuNo=2, name=李四, mark=87]
StuNode [stuNo=3, name=小明, mark=70]
StuNode [stuNo=4, name=小红, mark=90]
删除后的链表
StuNode [stuNo=1, name=张三, mark=85]
StuNode [stuNo=2, name=李四, mark=87]
StuNode [stuNo=4, name=小红, mark=90]
输出
数据结构之链表(LinkedList)(二)的更多相关文章
- 数据结构之链表(LinkedList)(三)
数据结构之链表(LinkedList)(二) 环形链表 顾名思义 环形列表是一个首尾相连的环形链表 示意图 循环链表的特点是无须增加存储量,仅对表的链接方式稍作改变,即可使得表处理更加方便灵活. 看一 ...
- Python与数据结构[0] -> 链表/LinkedList[0] -> 单链表与带表头单链表的 Python 实现
单链表 / Linked List 目录 单链表 带表头单链表 链表是一种基本的线性数据结构,在C语言中,这种数据结构通过指针实现,由于存储空间不要求连续性,因此插入和删除操作将变得十分快速.下面将利 ...
- 数据结构之链表(LinkedList)(一)
链表(Linked List)介绍 链表是有序的列表,但是它在内存中是存储如下 1)链表是以节点方式存储的,是链式存储 2)每个节点包含data域(value),next域,指向下一个节点 3)各个节 ...
- Python与数据结构[0] -> 链表/LinkedList[1] -> 双链表与循环双链表的 Python 实现
双链表 / Doubly Linked List 目录 双链表 循环双链表 1 双链表 双链表和单链表的不同之处在于,双链表需要多增加一个域(C语言),即在Python中需要多增加一个属性,用于存储指 ...
- Python与数据结构[0] -> 链表/LinkedList[2] -> 链表有环与链表相交判断的 Python 实现
链表有环与链表相交判断的 Python 实现 目录 有环链表 相交链表 1 有环链表 判断链表是否有环可以参考链接, 有环链表主要包括以下几个问题(C语言描述): 判断环是否存在: 可以使用追赶方法, ...
- 《数据结构与算法分析——C语言描述》ADT实现(NO.00) : 链表(Linked-List)
开始学习数据结构,使用的教材是机械工业出版社的<数据结构与算法分析——C语言描述>,计划将书中的ADT用C语言实现一遍,记录于此.下面是第一个最简单的结构——链表. 链表(Linked-L ...
- 数据结构-List接口-LinkedList类-Set接口-HashSet类-Collection总结
一.数据结构:4种--<需补充> 1.堆栈结构: 特点:LIFO(后进先出);栈的入口/出口都在顶端位置;压栈就是存元素/弹栈就是取元素; 代表类:Stack; 其 ...
- 基本数据结构:链表(list)
copy from:http://www.cppblog.com/cxiaojia/archive/2012/07/31/185760.html 基本数据结构:链表(list) 谈到链表之前,先说一下 ...
- SDUT 2142 数据结构实验之图论二:基于邻接表的广度优先搜索遍历
数据结构实验之图论二:基于邻接表的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Descript ...
随机推荐
- 解决 service iptables save 报错 please try to use systemctl
本文档根据 service iptables save 报错 please try to use systemctl 提供解决方案.报错 [root@Jaking ~]# service iptabl ...
- linux本地检测tomcat是否启动成功
@参考文章 原文如下: linux本地检测如何tomcat是否启动成功? 解决方法: 1.curl 127.0.0.1:8080 第一可以知道本地是否可以访问tomcat,返回页面代码 2.tail ...
- 宣化上人:大佛顶首楞严经四种清净明诲浅释(1)(转自学佛网:http://www.xuefo.net/nr/article23/230609.html)
唐天竺·沙门般剌密帝译 宣化上人主讲 一九八三年四月十七日晚讲于万佛圣城 四种清净明诲,真实不虚 楞严经里的四种清净明诲:断淫.断杀.断偷.断妄,是息息相关的.若犯淫戒,就容易犯杀戒,也容易犯盗戒.妄 ...
- 基于Java API for WebSocket (JSR-356)的标准websocket客户端
maven依赖 springboot <dependency> <groupId>org.springframework.boot</groupId> <ar ...
- 【OpenGL开发】关于GLEW扩展库
GLEW是一个跨平台的C++扩展库,基于OpenGL图形接口.使用OpenGL的朋友都知道,window目前只支持OpenGL1.1的涵数,但 OpenGL现在都发展到2.0以上了,要使用这些Open ...
- Django时区导致的datetime时间比较报错
我们使用python 的datetime模块比较Django数据库Datetime字段的时候,可能会出现报错: TypeError: can't compare offset-naive and of ...
- python 爬虫实例(四)
环境: OS:Window10 python:3.7 爬取链家地产上面的数据,两个画面上的数据的爬取 效果,下面的两个网页中的数据取出来 代码 import datetime import threa ...
- input 标签鼠标放入输入框补全提示
JSP: <input type="text" placeholder="eventDesc" value="" id="e ...
- 【剑指offer】面试题 42. 连续子数组的最大和
面试题 42. 连续子数组的最大和 NowCoder 题目描述 输入一个整型数组,数组里有正数也有负数.数组中一个或连续的多个整数组成一个子数组.求所有子数组的和的最大值. 示例: 输入: [-2,1 ...
- [转帖]C语言计算时间函数 & 理解linux time命令的输出中“real”“user”“sys”的真正含义
C语言计算时间函数 & 理解linux time命令的输出中“real”“user”“sys”的真正含义 https://blog.csdn.net/willyang519/article/d ...