数据结构之链表(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)(二)的更多相关文章

  1. 数据结构之链表(LinkedList)(三)

    数据结构之链表(LinkedList)(二) 环形链表 顾名思义 环形列表是一个首尾相连的环形链表 示意图 循环链表的特点是无须增加存储量,仅对表的链接方式稍作改变,即可使得表处理更加方便灵活. 看一 ...

  2. Python与数据结构[0] -> 链表/LinkedList[0] -> 单链表与带表头单链表的 Python 实现

    单链表 / Linked List 目录 单链表 带表头单链表 链表是一种基本的线性数据结构,在C语言中,这种数据结构通过指针实现,由于存储空间不要求连续性,因此插入和删除操作将变得十分快速.下面将利 ...

  3. 数据结构之链表(LinkedList)(一)

    链表(Linked List)介绍 链表是有序的列表,但是它在内存中是存储如下 1)链表是以节点方式存储的,是链式存储 2)每个节点包含data域(value),next域,指向下一个节点 3)各个节 ...

  4. Python与数据结构[0] -> 链表/LinkedList[1] -> 双链表与循环双链表的 Python 实现

    双链表 / Doubly Linked List 目录 双链表 循环双链表 1 双链表 双链表和单链表的不同之处在于,双链表需要多增加一个域(C语言),即在Python中需要多增加一个属性,用于存储指 ...

  5. Python与数据结构[0] -> 链表/LinkedList[2] -> 链表有环与链表相交判断的 Python 实现

    链表有环与链表相交判断的 Python 实现 目录 有环链表 相交链表 1 有环链表 判断链表是否有环可以参考链接, 有环链表主要包括以下几个问题(C语言描述): 判断环是否存在: 可以使用追赶方法, ...

  6. 《数据结构与算法分析——C语言描述》ADT实现(NO.00) : 链表(Linked-List)

    开始学习数据结构,使用的教材是机械工业出版社的<数据结构与算法分析——C语言描述>,计划将书中的ADT用C语言实现一遍,记录于此.下面是第一个最简单的结构——链表. 链表(Linked-L ...

  7. 数据结构-List接口-LinkedList类-Set接口-HashSet类-Collection总结

    一.数据结构:4种--<需补充> 1.堆栈结构:     特点:LIFO(后进先出);栈的入口/出口都在顶端位置;压栈就是存元素/弹栈就是取元素;     代表类:Stack;     其 ...

  8. 基本数据结构:链表(list)

    copy from:http://www.cppblog.com/cxiaojia/archive/2012/07/31/185760.html 基本数据结构:链表(list) 谈到链表之前,先说一下 ...

  9. SDUT 2142 数据结构实验之图论二:基于邻接表的广度优先搜索遍历

    数据结构实验之图论二:基于邻接表的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Descript ...

随机推荐

  1. Java基础 do-while 简单示例

        JDK :OpenJDK-11      OS :CentOS 7.6.1810      IDE :Eclipse 2019‑03 typesetting :Markdown   code ...

  2. dtypes.py", line 499 _np_qint8 = np.dtype([("qint8", np.int8, (1,)])

    Traceback (most recent call last): File "<stdin>", line 1, in <module> File &q ...

  3. 使用 evo 工具评测 VI ORB SLAM2 在 EuRoC 上的结果

    http://www.liuxiao.org/2017/11/%E4%BD%BF%E7%94%A8-evo-%E5%B7%A5%E5%85%B7%E8%AF%84%E6%B5%8B-vi-orb-sl ...

  4. xml文档操作

    /** * */package com.gootrip.util; import java.io.ByteArrayOutputStream;import java.io.File;import ja ...

  5. 报错:Exception: org.apache.sqoop.common.SqoopException Message: DRIVER_0002:Given job is already running - Job with id 1

    报错背景: 创建完成job之后,执行job的时候报错. 报错现象: Exception: org.apache.sqoop.common.SqoopException Message: CLIENT_ ...

  6. Python - Django - ORM 不常用字段

    BigAutoField(AutoField): bigint 自增列,必须填入参数 primary_key=True 如果没有写自增列,则会自动创建一个列名为 id 的列 SmallIntegerF ...

  7. 函数返回new对象

    #include <iostream> using namespace std; // foo()函数本质上没什么问题,但建议你不要这样写代码 string &foo() { st ...

  8. Java以UTF-8格式读写及追加写文件示例

    package test; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; im ...

  9. Python:实现图片裁剪的两种方式——Pillow和OpenCV

    原文:https://blog.csdn.net/hfutdog/article/details/82351549 在这篇文章里我们聊一下Python实现图片裁剪的两种方式,一种利用了Pillow,还 ...

  10. Vue + ElementUI的电商管理系统实例03 用户列表

    1.通过路由展示用户列表页 新建user文件夹,里面新建Users.vue文件: <template> <div> <h3>用户列表组件</h3> &l ...