资讯专栏INFORMATION COLUMN

【数据结构 Java 版】玩转链表(3)双链表

G9YH / 1810人阅读

摘要:文章目录一引子二双链表概念结构基操的实现三总结一引子前面已经了解了顺序表和单链表,而在面试当中这些也是经常被提起的在继续接下来的学习前,我们要搞清以下几个问题数组和链表的区别顺序表和链表的区别和的区别大家发现没上述问题

一、引子

前面已经了解了顺序表和单链表,而在面试当中这些也是经常被提起的

在继续接下来的学习前,我们要搞清以下几个问题:

  1. 数组和链表的区别
  2. 顺序表和链表的区别
  3. ArrayList 和 LinkedList 的区别

大家发现没上述问题本质上都是同一个问题:顺序表和链表的区别

那么怎么回答呢?我们可以从共性开始介绍

  1. 怎么组织数据的?

    • 对于顺序表: 底层是一个数组
    • 对于链表: 每个数据是由节点组织的(由节点与节点之间的指向组织)
  2. 增删查改

    • 对于顺序表: 不适合插入和删除,适合查找和修改
    • 对于链表: 不适合查找和修改,适合插入和删除
  3. 等等

注意:

  • ArrayList 和 LinkedList 这两个类是 Java 中的集合类,是封装好的顺序表和链表
  • LinkedList 底层是一个双向链表

既然学了单链表,我们也要对双链表进行学习,这肯定也很重要,不然为啥 Java 的 LinkedList 底层是一个双链表呢!

那什么是双链表呢?

二、双链表

1. 概念

【数据结构 Java 版】玩转链表(1)单链表+链表面试题 这章中我们用一图简单介绍了双向链表的样子

与单链表不同的是

  • 它引入了一个前驱域 prev,解决了单链表只能单向访问的痛点
  • 在头节点 head 的前提下,还可以增加一个尾节点 last,标志尾巴,这样可以方便尾插法

2. 结构

那么怎么实现一个双链表呢?

首先我们依然要定义一下节点

class NodeD{    public int val;    public NodeD prev;    public NodeD next;        public NodeD(int val){        this.val=val;    }}

和单链表差不多,只是增加了个前驱节点

再对双链表进行定义

public class MyRealLinkedList {    public NodeD head;    public NodeD last;}

在单链表的基础上多了个尾节点

接下来我们来实现双向不带头非循环链表的一些操作,是我们对其的理解更加深透

3. 基操的实现

  1. 头插法

    public void addFirst(int data){    NodeD node=new NodeD(data);    if(this.head==null){        this.head=node;    }else{        node.next=this.head;        this.head.prev=node;        this.head=node;    }}
  2. 尾插法

    public void addLast(int data){    NodeD node=new NodeD(data);    if(this.head==null){        this.head=node;        this.last=node;    }else{        this.last.next=node;        node.prev=last;        this.last=node;}
  3. 任意位置插入,第一个数据节点为0号下标

    public void addIndex(int index,int data){    if(index<0 || index >size()){        throw new RuntimeException("index 不合法");    }    if(index==0){        addFirst(data);    }    if (index == size()) {        addLast(data);    }    NodeD node=new NodeD(data);    NodeD cur=searchNode(index);    node.next=cur;    cur.prev.next=node;    node.prev=cur.prev;    cur.prev=node;}
  4. 搜索下标为 index 的数据节点节点

    public NodeD searchNode(int index){    int i=0;    NodeD cur=this.head;    while(i!=index){        cur=cur.next;        i++;    }    return cur;}
  5. 查找关键字 key 是否在单链表中

    public boolean contains(int key){    if(this.head==null){        return false;    }    NodeD cur=this.head;    while(cur!=null){        if(cur.val==key){            return true;        }        cur=cur.next;    }    return false;}
  6. 删除第一次出现的关键字为 key 的节点

    public void remove(int key){    if(this.head==null){        return;    }    NodeD cur=this.head;    while(cur!=null) {        if (cur.val == key) {            if (cur == this.head) {                this.head = this.head.next;                if(this.head!=null) {                    this.head.prev = null;                }else{                    this.last=null;                }            }else {                cur.prev.next = cur.next;                if (cur == this.last) {                    last = cur.prev;                }else {                    cur.next.prev = cur.prev;                }            }            return;        } else {            cur = cur.next;        }    }}
  7. 删除所有关键字为 key 的节点

    public void removeAllKey(int key){    if(this.head==null){        return;    }    NodeD cur=this.head;    while(cur!=null) {        if (cur.val == key) {            if (cur == this.head) {                this.head = this.head.next;                if (this.head != null) {                    this.head.prev = null;                } else {                    this.last = null;                }            } else {                cur.prev.next = cur.next;                if (cur == this.last) {                    last = cur.prev;                } else {                    cur.next.prev = cur.prev;                }            }        }        cur = cur.next;    }}
  8. 得到双链表的长度

    public int size(){    if(this.head==null){        return 0;    }    NodeD cur=this.head;    int count=0;    while(cur!=null){        count++;        cur=cur.next;    }    return count;}
  9. 清除双链表

    public void clear(){    NodeD cur=this.head;    while(cur!=null){        NodeD curNext=cur.next;        cur.prev=null;        cur.next=null;        cur=curNext;    }    this.head=null;    this.last=null;}
  10. 打印双链表

    public void display(){    if(this.head==null){        return;    }    NodeD cur=this.head;    while(cur!=null){        System.out.print(cur.val + " ");        cur=cur.next;    }    System.out.println();}

三、总结

到此为止,链表我们已经基本认识了,而接下来我们就是通过刷题和积累,去沉淀自己!希望大家看完这篇文章,可以真正的玩转链表!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/119637.html

相关文章

  • 数据结构[双的实现,以及双和单之间的比较,和顺序的优劣]

    摘要:它在单链表的基础上优化了很多,例如尾插法等就不用了逐个遍历链表节点,直接就可以找到链表的为节点,实现与添加的新节点连接。文件在文件中实现双向链表的测试,测试双向链表的功能。 ...

    xingqiba 评论0 收藏0
  • 数据结构 - 收藏集 - 掘金

    面试旧敌之红黑树(直白介绍深入理解) - Android - 掘金 读完本文你将了解到: 什么是红黑树 黑色高度 红黑树的 5 个特性 红黑树的左旋右旋 指定节点 x 的左旋 右图转成左图 指定节点 y 的右旋左图转成右图 红黑树的平衡插入 二叉查找树的插入 插入后调整红黑树结构 调整思想 插入染红后... java 多线程同步以及线程间通信详解 & 消费者生产者模式 & 死锁 & Thread...

    leeon 评论0 收藏0
  • Java数据结构与算法——

    摘要:前言数据结构与算法专题会不定时更新,欢迎各位读者监督。本文介绍另一种数据结构链表,包括链表的特点特点链表的创建删除插入和输出,文末给出代码和一道常见的关于链表的面试题。 声明:码字不易,转载请注明出处,欢迎文章下方讨论交流。 前言:Java数据结构与算法专题会不定时更新,欢迎各位读者监督。本文介绍另一种数据结构——链表,包括链表的特点特点、链表的创建、删除、插入和输出,文末给出java...

    CKJOKER 评论0 收藏0
  • 实战PHP数据结构基础之双

    摘要:什么是双链表上一篇实战数据结构基础之单链表说到单链表由一个一个的作为节点的对象构成的,每一个节点都有指向下一个节点的指针,最后一个节点的指针域指向空。 什么是双链表? 上一篇实战PHP数据结构基础之单链表说到 单链表由一个一个的作为节点的对象构成的,每一个节点都有指向下一个节点的指针,最后一个节点的指针域指向空。每个节点可以存储任何数据类型。 而双链表每个节点有两个指针域,分别指向前驱...

    Michael_Lin 评论0 收藏0
  • <LeetCode天梯>Day026 反转(递归法+(迭代法)双法) | 初级算法 | Py

    摘要:关于递归这里提一两点递归基本有这几步递归的模板,终止条件,递归调用,逻辑处理。 ?作者简介:大家好,我是车神哥,府学路18号的车神? ?个人主页:应无所住而生...

    imingyu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<