双向链表详解

2023-11-20

目录

一,双向链表的概念及结构 

二,双向链表的方法及其实现

2.1 双向链表

2.2 addFirst(int data) - 头插法 

2.3 addLast(int data) - 尾插法

2.4 size() - 链表长度

2.5 display() - 打印链表内容

2.6 clear() - 删除链表

2.7 addIndex(int index, int data) - 任意位置插入

2.8 contains(int key) - 链表当中是否有key

2.9 remove(int key) - 删除链表中第一次出现的key

2.10 removeAllKey(int key) - 删除所有值为key的节点


一,双向链表的概念及结构 

与单向链表相同,只不过每一个节点中多了一个空间来存储上一个节点的地址,结构如下图所示:

二,双向链表的方法及其实现

2.1 双向链表

链表类的定义及我们接下来要实现的方法,如下代码:

public class LinkedList {
    static class ListNode{//节点类 - 因为节点是链表的属性,所以用static来修饰
        //节点的成员
        public int val;
        public ListNode prev;
        public ListNode next;
        public ListNode(int val){
            this.val = val;
        }
    }
    public ListNode head;//头节点 - 不是每个节点都是头节点,它是链表的属性,所以定义在节点类外面
    public ListNode last;//尾节点 - 同头节点

    //头插法
    public void addFirst(int data){}

    //尾插法
    public void addLast(int data){}

    //在任意位置插入,假设第一个节点的下标为0
    public void addIndex(int index, int data){}

    //查找是否包含关键字key是否在单链表当中
    public boolean contains(int key){}

    //删除第一次出现关键字为key的节点
    public void remove(int key){}

    //删除所有值为key的节点
    public void removeAllKey(int key){}

    //得到单链表的长度
    public int size(){}

    //打印链表内容
    public void display(){}

    //删除链表
    public void clear(){}
}

2.2 addFirst(int data) - 头插法 

顾名思义,就是在头节点之前插入一个节点,并将其变成头节点。 如图

但是我们还要注意如果链表当中没有元素的情况,如图:

    public void addFirst(int data){
        ListNode node = new ListNode(data);//创建一个节点
        if(head == null){//无元素的情况
            head = node;
            last = node;
            return;
        }
        head.prev = node;//1
        node.next = head;//2
        head = node;//4
    }

2.3 addLast(int data) - 尾插法

 但是我们还要注意如果链表当中没有元素的情况,如图:

    public void addLast(int data){
        ListNode node = new ListNode(data);
        if(head == null){
            head = node;
            last = node;
            return;
        }
        last.next = node;
        node.prev = last;
        last = node;
    }

2.4 size() - 链表长度

遍历链表

    public int size(){
        ListNode cur = head;//不能直接用head遍历,会改变head节点
        int count = 0;
        while(cur != null){
            cur = cur.next;
            count++;
        }
        return count;
    }

2.5 display() - 打印链表内容

遍历链表

    public void display(){
        ListNode cur = head;
        while(cur != null){
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();//换行
    }

2.6 clear() - 删除链表

遍历链表 - 将所有值置为空

    public void clear(){
        ListNode cur = head;        
        while (cur != null) {
            ListNode curNext = cur.next;
            cur.prev = null;
            cur.next = null;
            cur = curNext;
        }
        head = null;
        last = null;
    }

2.7 addIndex(int index, int data) - 任意位置插入

1.  要先判断他输入的下标合不合法

2.  看下标是不是头节点,尾节点,是的话直接调用头插法,尾插法

3.  如图

   public void addIndex(int index,int data){
        if(index < 0 || index > size()) {
            System.out.println("index不合法!");
            return;
        }
        if(index == 0) {
            addFirst(data);
            return;
        }
        if(index == size()) {
            addLast(data);
            return;
        }
        //cur拿到了index下标的节点的地址
        ListNode cur = head;
        while (index != 0) {
            cur = cur.next;
            index--;
        }
        ListNode node = new ListNode(data);
        node.prev = cur.prev;
        node.next = cur;
        cur.prev.next = node;
        cur.prev = node;
    }

2.8 contains(int key) - 链表当中是否有key

遍历链表

      public boolean contains(int key){
        ListNode cur = head;
        while (cur != null){
            if(cur.val == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

2.9 remove(int key) - 删除链表中第一次出现的key

1. 先找到key所在的位置

2. 判断是不是头节点,如果是且不只有一个元素 

如果是头节点且只有一个头节点:

3. 再判断是不是尾节点,如果是:

4.是中间节点,如图:

 

    public void remove(int key){
        ListNode cur = head;
        while(cur != null){
            if(cur.val == key){
                if(cur == head){
                    head = head.next;
                    if(head == null){//只有一个元素
                        last = null;
                    }else {//有多个元素
                        head.prev = null;
                    }
                }else {
                    if(cur == last){//尾节点
                        last = last.prev;
                        last.next = null;
                    }else {//中间节点
                        cur.prev.next = cur.next;
                        cur.next.prev = cur.prev;
                    }
                }
                return;
            }
            cur = cur.next;
        }
    }

2.10 removeAllKey(int key) - 删除所有值为key的节点

与remove方法相同,只不过删除成功后不要return,继续往后遍历:

    public void removeAllKey(int key){
        ListNode cur = head;
        while(cur != null){
            if(cur.val == key){
                if(cur == head){
                    head = head.next;
                    if(head == null){
                        last = null;
                    }else {
                        head.prev = null;
                    }
                }else {
                    if(cur == last){//尾节点
                        last = last.prev;
                        last.next = null;
                    }else {
                        cur.prev.next = cur.next;
                        cur.next.prev = cur.prev;
                    }
                }
                //return这里不同
            }
            cur = cur.next;
        }
    }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

双向链表详解 的相关文章

  • HTML-Entity 转义以防止 XSS

    我有一些用户输入 在我的代码中 我确保对以下符号进行转义 gt amp lt gt lt gt gt gt OWASP https www owasp org index php XSS 28Cross Site Scripting 29
  • 外部硬件指纹扫描仪和 Android 设备集成

    我想建立一个android像员工考勤这样的应用程序使用fingerprint scanner 我想知道 是否可以使用外部硬件设备进行指纹识别 扫描 如何将Android应用程序与外部硬件finger集成 打印扫描设备 如何从外部硬件设备获取
  • 在多个不同线程之间共享变量

    我想在多个线程之间共享一个变量 如下所示 boolean flag true T1 main new T1 T2 help new T2 main start help start 我想分享flag在主线程和帮助线程之间 这是我创建的两个不
  • Maven 管理的 Java EE 应用程序中 JBoss 提供的库

    这对我来说实际上不太可能 但网上似乎没有关于将 JBoss 提供的依赖项导入 Maven 管理的 Java EE 应用程序以在其中部署的直接答案 据我所知 有两件事与这个问题有关 那就是jboss as client外部 就 JVM 而言
  • 构建 jar 后无法运行 exe

    我制作了一个简单的实用应用程序 其中我有一个要运行的exe文件 我通过使用它来运行 Runtime getRuntime exec this getClass getResource filename exe getPath 当我从 ide
  • Spring Boot 是否支持服务器名称指示(SNI)?

    Spring Boot 是否支持服务器名称指示 SNI 具体来说 运行嵌入式 Tomcat 服务器并打包为可执行 jar 文件的 Spring Boot 2 2 2 RELEASE 应用程序是否可以根据传入请求的主机名支持多个 SSL 证书
  • Java中的String为什么是不可变的对象,但我在创建一个对象后仍然可以更改它的值? [复制]

    这个问题在这里已经有答案了 如果我可以创建一个字符串并给它一个值 这怎么可能呢 然后 我可以像这样简单地覆盖它的值 String a abc a def 我怎么可能改变的值a 我一定在这里遗漏了一些东西 我知道每当创建 String 对象时
  • 无法在 Spring boot 中使用 findOne() 方法

    我的项目是关于用户管理器网络的 我是 Spring 和 Java 的新手 这是我的代码 在 UserController 中 RequestMapping value users name method RequestMethod GET
  • Clojure Web 应用程序 - 我从哪里开始?

    最近我一直在研究 Clojure 我喜欢这门语言 我想看看我是否可以在其中制作一个小型网络应用程序 只是为了挑战自己 但是 我完全没有设置任何与 Java 相关的 Web 应用程序的经验 事实上 我对 Java 并没有太多的经验 我从哪说起
  • Java 中的逻辑回归

    我们需要用 Java 进行逻辑回归 我们在 Python 中使用了这段代码http blog smellthedata com 2009 06 python logistic regression with l2 html http blo
  • 将 JAR 文件打包为 WAR 文件

    我有一系列依赖的Java项目 我想将它们打包成一个 JAR 文件 以便在我的 WAR 文件中使用 这些项目依赖于大量的外部库和项目 如log4j apache commons等 我选择 Eclipse 中的所有项目并导出为 JAR 文件 然
  • 与 Java 中的同步块相比,新的 Lock 接口有什么优势?

    与 Java 中的同步块相比 新的 Lock 接口有什么优势 您需要实现一个高性能缓存 允许多个读取器但单个写入器保持完整性 您将如何实现它 锁的优点是 让他们公平是可能的 可以使线程在等待 Lock 对象时响应中断 可以尝试获取锁 但如果
  • 如何从 Java 类调用 Kotlin 类

    我需要将意图从 java 活动传递到 Kotlin 活动 Java活动ProfileActivity class Intent selectGameIntent new Intent ProfileActivity this kotlin
  • 如何将捕获的图像写入/粘贴到文档文件?

    我有一个场景 我需要捕获图像并将它们一个接一个地写入到一个word文件中 我已经编写了下面的代码 但似乎不起作用 请帮忙 Robot robot try robot new Robot BufferedImage screenShot ro
  • 定时器启动/停止参数

    自从加入这个社区以来 我在技能和进步方面取得了突飞猛进的进步 你们都是一个巨大的帮助 我无法提供一个计时器 该计时器已在启动和停止时实现了某些参数 我要么收到错误消息 局部变量计时器可能尚未初始化 要么没有收到错误消息 但什么也没有发生 也
  • 使用服务器 java api 从 jasperserver 存储库检索资源

    我正在尝试使用其 java API 从 Jasperserver 存储库检索资源 根据jasper 报表服务器终极指南 https community jaspersoft com documentation jasperreports s
  • java:验证 GUI 中的所有文本字段是否已完成

    我正在尝试创建一个允许某人设置帐户的 GUI 我想验证按下创建帐户按钮时所有文本字段是否完整 做这个的最好方式是什么 我正在附加我的代码 但我对文本字段是否完整的验证不起作用 参见下面的代码 public class GUIaccounts
  • jstack 是否停止在较新的 JDK8 版本上工作?

    我惊讶地发现 不知何故 最近 jstack 停止了在较新的 JDK 8 上的工作 我不确定这发生在哪个版本 但我确实得到 36649 Unable to open socket file target process not respond
  • OkHttp javax.net.ssl.SSLPeerUnverifiedException:主机名domain.com未验证

    我几天来一直在努力让它发挥作用 我正在尝试通过以下方式连接到我的服务器https带有自签名证书 我认为现在没有任何页面或示例是我未读过的 我做了什么 按照本教程创建了 bks 密钥库 http blog crazybob org 2010
  • hibernate通过主键查询

    我想通过主键创建查询 假设我有类主键 PersonKey 属性是 name 和 id 我有 Person 类 属性是 PersonKey 地址 DOB 现在 我想通过主键搜索人员 首先 我创建 PersonKey 的实例 并将名称设置为 j

随机推荐

  • 互联网寒冬?应届生还应该加入么?

    大家都在各种唱衰互联网行业 下面从真实的示例来分析一下 还能否加入这个行业 互联网企业现状 互联网企业地域分布 从业者从一线城市逐渐向低线扩展 对新一线及低线城市的青睐度上升 腾讯地域扩张 腾讯业务版图 阿里地域扩张 阿里业务版图 字节地域
  • PhpStorm为什么值得推荐?

    智能编码辅助 PhpStorm 是一个 PHP IDE 它实际上 获取 您的代码 它支持 PHP 5 3 5 4 5 5 5 6 7 0 7 1 7 2 提供动态错误预防 最佳自动完成和代码重构 零配置调试以及扩展的 HTML CSS 和J
  • sql ntext數據類型字符替換

    ntext數據類型字符替換 2011 08 21 塗聚文 create table tt sid INT IDENTITY 1 1 cont ntext go insert into tt cont values N fd sad fdsa
  • Qt 信号与槽

    Qt 信号与槽 在这章节里 我们学习 Qt 的信号与槽 这里分一个章节来学习这个 Qt 的信号与槽 可见 这个信号与槽有多么重要 在学习 Qt 的过程中 信号与槽是必不可少的部分 也是 Qt 编程的 基础 是 Qt 编程的一大创新 其实与
  • 文件通讯录

    copyright C 2014 2015 Lighting Studio Co Ltd File name Author Jerey Jobs Version 0 1 Date Description Funcion List inclu
  • 世界最强的黑客为何都在俄罗斯?他们到底有多逆天?

    世界上只有两种黑客 一种 是俄罗斯黑客 另一种 是 其他黑客 江湖传闻 俄罗斯黑客曾攻击美国政府网站 操纵美国大选 就连FBI都怕他们三分 今天带大家认见识见识战斗民族的另一面 黑客帝国 俄罗斯的黑客有多逆天 1994年成名战 美国最大的银
  • 用where in遇到null时的解决方法1

    参考 https www 2cto com database 201109 104960 html http ask csdn net questions 680006 1 SELECT FROM 华东 WHERE 公司代码 IN SELE
  • Matlab将mat格式文件多层数据逐级导出为excel

    我在处理牛津电池数据集时 因为我更喜欢用python来进行深度学习方面的操作 所以我需要将mat格式数据导出为excel表格 由于该数据分为多层 所以导出操作较为复杂 在网上查询许久后发现并没有相关的文章 后来便自己倒腾出来了 供需要的小伙
  • GPU 渲染管线与着色器 大白话总结 ---- 一篇就够

    转载自 https blog csdn net newchenxf article details 119803489 真的写的非常不错 大力推荐 GPU 渲染管线与着色器 大白话总结 一篇就够 文章目录 GPU 渲染管线与着色器 大白话总
  • uboot下UCLASS框架详解---结合项目工作中spi master和flash驱动开发

    文章目录 一 综述 二 UCLASS架构解析 2 1 uclass 2 2 udevice 2 3 uclass driver 2 4 driver 2 4 1 spi master driver 三 uboot代码解析 3 1 DM的初始
  • 北京理工大学计算机系郭伟,【记忆辉煌2014】品学兼优榜样——郭伟(2012级研究生)...

    青春宣言 自强不息 厚德载物 个人简介文章情况 1 Guo Wei et al Insect vision inspired particle filter for visual tracking Robotics and Biomimet
  • 微信小程序接入支付功能并实现支付

    随着微信小程序越来越广泛的应用 现在小程序几乎无所不能 绝对啦 哈哈 那么就会有很多微信小程序需要有支付的需求 那么该文章将带领大家走一遍如何实现微信小程序的支付功能 第一步 微信小程序管理后台 gt 微信支付 gt 接入微信支付 及关联
  • 0基础也能看懂,熬夜7天肝出这一份3w字软件测试学习手册【建议收藏】

    随着互联网行业的发展迅速 很多人都想涌进来 近年来软件测试岗位也呈现出了前所未有的火爆趋势 尤其2021年国家实现教育 双减 政策 激起了很多教培从业者 幼师 机械加入软件测试行业学习 剑哥今天抽个时间简单的给大家说下 对于0基础的朋友到底
  • python3图像处理_Python3与OpenCV3.3 图像处理(二)--图像基本操作

    一 本节简述 本节主要讲解图像的一些基础知识 以及图像的加载和获得属性 最后将会学到 OpenCV 摄像头的简单使用 二 图像基本知识 1 图像是什么 图像是客观对象的一种相似性的 生动性的描述或写真 是人类社会活动中最常用的信息载体 或者
  • CST2020 安装包和安装步骤

    安装包和破解码的百度云链接 链接 https pan baidu com s 1RNSWxVxb DIu8dg8gkCzAw 提取码 dve7 如果失效可评论留言 谢谢 1 关闭防火墙和杀毒软件 2 解压后 以管理员模式运行setup文件
  • 使用inet_ntop转换IPv6地址时在macOS和linux上的行为不一样

    下面这段python代码在macOS和linux时运行的结果是不同的 import socket ip socket inet pton socket AF INET6 1 2 3 0 5 6 7 8 print socket inet n
  • ubuntu20.04 apt 安装报 E: Unable to correct problems, you have held broken packages.

    在安装软件的时候报错 root root sudo apt get install vim Reading package lists Done Building dependency tree Reading state informat
  • Leetcode刷题日志5.0

    目录 前言 1 两数相加 2 无重复字符的最长子串 3 整数反转 4 删除链表的倒数第 N 个结点 前言 今天我又来继续分享最近做的题了 现在开始进入我们快乐的刷题时间吧 编程语言Python3 0 难度 中等 1 两数相加 给你两个 非空
  • Redis工具类(缓存操作,Object转换成JSON数据)

    依赖spring data redis 2 4 1 jar Component Data public class RedisUtils Autowired private RedisTemplate
  • 双向链表详解

    目录 一 双向链表的概念及结构 二 双向链表的方法及其实现 2 1 双向链表 2 2 addFirst int data 头插法 2 3 addLast int data 尾插法 2 4 size 链表长度 2 5 display 打印链表