【数据结构与算法】4、双向链表(学习 jdk 的 LinkedList 部分源码)

news2025/1/13 6:28:21

目录

  • 一、双向链表
  • 二、node(int index) 根据索引找节点
  • 三、clear()
  • 四、add(int, E)
  • 五、remove(int index)
  • 六、双向链表和单链表
  • 七、双向链表和动态数组
  • 八、jdk 官方的 LinkedList 的 clear() 方法

一、双向链表

在这里插入图片描述

🎁 单链表的节点中只有一个 next 指针引用着下一个节点的地址
🎁 当要获取单链表中的最后一个元素的时候,需要从头节点开始遍历到最后
🎁 单链表一开始的时候有 first 头指针引用着头节点的地址

💰 双向链表可以提升链表的综合性能
💰 双向链表的节点中有 prev 指针引用着一个节点的地址,有 next 指针引用着一个节点的地址
💰 双向链表中一开始的时候有 first 头指针引用着头节点的地址,有 last 尾指针引用着尾节点的地址
💰 ① 当需要获取双向链表靠后的节点【index >= (size / 2)】的时候从尾节点开始遍历;② 当需要获取双向链表靠前的节点【index < (size / 2)】的时候从头节点开始遍历

🎄 头节点的 prev 为 null
🎄 尾节点的 next 为 null

二、node(int index) 根据索引找节点

  /**
   * 根据索引找节点
   */
  private Node<E> node(int index) {
      rangeCheck(index);

      if (index < (index >> 1)) { // 找左边的节点
          Node<E> node = first;
          for (int i = 0; i < index; i++) {
              node = node.next;
          }
          return node;
      } else {
          Node<E> node = last;
          for (int i = size - 1; i > index; i--) {
              node = node.prev;
          }
          return node;
      }
  }

三、clear()

  @Override
  public void clear() {
      size = 0;
      first = null;
      last = null;
  }

只有被【gc root 对象】引用的对象才不会被垃圾回收器回收:

🍃 被栈指针(局部变量)引用的对象是 gc root 对象

在这里插入图片描述

在这里插入图片描述

四、add(int, E)

在这里插入图片描述

🎄 ① 当往索引 0 处插入节点的时候
🎄 ② 当往最后插入节点的时候
🎄 ③ 当一个节点都没有(插入第一个节点)的时候

在这里插入图片描述

在这里插入图片描述

    @Override
    public void add(int index, E element) {
        rangeCheck4Add(index);

        if (size == 0 || (first == null && last == null)) { // 添加第一个节点
            // 新节点的 prev 和 next 都指向 null
            first = new Node<>(element, null, null);
            // 头指针和尾指针都指向新节点
            last = first;
        } else {
            if (index == size) { // 往最后插入新节点
                Node<E> oldLast = last;
                last = new Node<>(element, oldLast, null);
                oldLast.next = last;
            } else {
                // 找到 index 索引处的节点(该节点是新节点的下一个节点)
                Node<E> next = node(index);
                // 前一个节点(假如是往索引为 0 的位置插入节点的话, prev 是 null)
                Node<E> prev = next.prev;

                // 新节点的 prev 指向【前一个节点】
                // 新节点的 next 指向【后一个节点】
                Node<E> newNode = new Node<>(element, prev, next);

                // 后一个节点的 prev 指向新节点
                next.prev = newNode;

                /* 往索引为 0 处插入新节点 */
                if (prev == null) { // 往索引为 0 的位置插入新节点(插入新节点到头节点的位置)
                    first = newNode; // 头指针指向新节点
                } else {
                    // 前一个节点的 next 指向新节点
                    prev.next = newNode;
                }
            }
        }

        size++;
    }

在这里插入图片描述

五、remove(int index)

在这里插入图片描述

自己写的代码(测试成功的):

    @Override
    public E remove(int index) {
        rangeCheck(index);

        // 拿到 index 位置的节点
        Node<E> oldNode = node(index);

        if (index == 0) { // 删除头节点
            // 拿到头节点
            first = oldNode.next;
            first.prev = null;
        } else {
            oldNode.prev.next = oldNode.next;

            if (oldNode.next == null) { // 删除尾节点
                last = oldNode.prev;
            } else {
                oldNode.next.prev = oldNode.prev;
            }
        }

        size--;

        return oldNode.element;
    }

老师的代码:

    @Override
    public E remove(int index) {
        rangeCheck(index);

        Node<E> node = node(index);
        Node<E> prev = node.prev;
        Node<E> next = node.next;

        if (prev == null) { // 删除头节点
            first = next;
        } else {
            prev.next = next;
        }


        if (next == null) { // 删除尾节点
            last = prev;
        } else {
            next.prev = prev;
        }

        size--;

        return node.element;
    }

在这里插入图片描述

六、双向链表和单链表

在这里插入图片描述

🎉 双向链表相比单向链表操作数量缩减一半

七、双向链表和动态数组

🌱 动态数组:开辟、销毁内存空间的次数相对较少但可能造成内存空间浪费(可以通过缩容解决)
🌱 双向链表:开辟、销毁内存空间的次数相对较多(每次添加元素都会创建新的内存空间 ),但不会造成内存空间的浪费

🌿 如果需要频繁在尾部进行添加删除操作,动态数组双向链表 均可选择

  • 动态数组在尾部添加和删除都是 O(1) 级别的
  • 双向链表由于有尾指针 last 的存在,在尾部添加和删除的操作也是 O(1) 级别的

🌿 如果需要频繁在头部进行添加删除操作,建议选择使用 双向链表

  • 动态数组头部的添加和删除操作需要进行大量的元素挪动
  • 双向链表有头指针 first 的存在,在头部进行添加删除操作效率很高

🌿 如果需要频繁地(在任意位置)进行添加删除操作,建议选择使用双向链表

  • 动态数组有最坏情况(假如是在头部添加或删除几乎需要挪动全部元素)
  • 双向链表最多就遍历 n/2 次(n 是元素数量)

🌿 如果有频繁的查询操作(随机访问操作),建议选择使用动态数组

  • 动态数组的随机访问是 O(1) 级别的,通过下标 index 可以直接定位到元素的内存地址
  • 双向链表每次查询都需要遍历,最坏情况要遍历 size 次(size 是元素个数)

❓ 相比单链表,双向链表效率很高。哪有了双向链表,单向链表是否就没有任何用处了呢 ❓
🌿 哈希表的设计中就用到了单链表 😀

八、jdk 官方的 LinkedList 的 clear() 方法

在这里插入图片描述

  • 我学习数据结构与算法的全部代码:https://gitee.com/zgq666good/datastructureandalgorithm.git
  • 学习资料来自于我偶像 ~ 李明杰(小码哥教育)
    在这里插入图片描述

🌿如有错误,请不吝赐教🌿

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/693807.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1754_C语言assert函数功能初探

全部学习汇总&#xff1a; GreyZhang/c_basic: little bits of c. (github.com) 最近学习的过程中遇到了C语言中的assert函数&#xff0c;弄不明白这个函数到底是什么用。简单查了一下总结内容如下&#xff1a; 首先&#xff0c;此函数的声明头文件在assert.h中&#xff0c;使…

数据结构之哈夫曼树和哈夫曼编码

切入正题之前&#xff0c;我们先了解几个概念&#xff1a; 路径&#xff1a;从树的一个结点到另一个结点分支所构成的路线路径长度&#xff1a;路径上的分支数目树的路径长度&#xff1a;从根结点出发到每个结点的路径长度之和带权路径长度&#xff1a;该结点到根结点的路径长…

Spring概念:容器、Ioc、DI

目录 什么是容器&#xff1f; 什么是 IoC&#xff1f; 传统程序的开发 理解 Spring IoC DI 总结 我们通常所说的 Spring 指的是 Spring Framework&#xff08;Spring 框架&#xff09;&#xff0c;它是⼀个开源框架&#xff0c;有着活跃⽽庞⼤的社区&#xff0c;这就是它…

从C语言到C++_22(继承)多继承与菱形继承+笔试选择题

目录 1. 继承 1.1 继承的概念 1.2 继承的定义格式 1.3 访问限定符和继承方式 1.4 继承中的赋值 1.5 继承中的作用域 2. 子类(派生类)的默认成员函数 2.1 子类的构造函数 2.2 子类的拷贝构造函数 2.3 子类的赋值重载 2.4 子类的析构函数 2.5 小总结 3. 继承与友元…

欧洲运输业的创新能力评估报告(英)(附下载)

5月&#xff0c;联合研究中心(JRC)在交通研究与创新监测与信息系统&#xff08;TRIMIS&#xff09;上发布了一份报告&#xff0c;提供了对欧盟运输部门创新能力的最新评估。TRIMIS通过欧盟层面的宏观指标分析&#xff0c;对运输创新能力进行定期评估。 该报告分析了研究与开发(…

Tuxera NTFS2023Mac电脑免费U盘硬盘读写工具

Mac用户在使用NTFS格式移动硬盘时&#xff0c;会遇到无法写入硬盘的情况。要想解决无法写入的问题&#xff0c;很多人选择使用Mac读写软件。面对市面上“众多”的读写硬盘软件&#xff0c;用户应该怎么选择呢&#xff1f;初次接触移动硬盘的伙伴可能不知道移动硬盘怎么和电脑连…

探析ModaHub魔搭社区中文文本生成图片AI模型的现状、趋势和未来发展方向

目录 一、现状分析 二、趋势分析 三、未来预测 ModaHub魔搭社区是一个专注于AI模型开发和分享的平台&#xff0c;其中文本生成图片AI模型是其中的一个重要领域。本文将通过对ModaHub魔搭社区中文文本生成图片AI模型排行榜的数据分析&#xff0c;来探讨该领域的现状、趋势和未…

Linux安装nginx 反向代理 负载均衡 动静分离 高可用等使用

随着软件需求的发展&#xff0c;现在很多的系统都需要保证高可用、高并发&#xff0c;在此需求之下就需要部署的服务能够不间断的提供服务即避免单点故障问题因此系统需要做集群部署同时还能提升qps、tps等指标&#xff1b;集群部署后的服务就需要对用户的请求能够负载均衡&…

12 通用同步异步收发器(USART)

目录 通用同步异步收发器&#xff08;USART&#xff09; 理论部分 USART概览 STM32和PC通信模型 STM32和PC通过RS-232标准通信 RS-232标准介绍 RS-232协议电平标准对比 RS-232标准的物理接口规定及接口标号 RS-232标准下接口标号的作用 RS-232标准数据传输协议层 协议…

探索数字化前沿:数字化产品引领科技创新风潮

随着数字化时代的到来&#xff0c;国内数字化产品市场蓬勃发展&#xff0c;涌现出许多引领行业变革的产品。本文将介绍几个在数字孪生和人工智能领域取得突破的国内产品&#xff0c;带大家了解数字化产品的创新应用和影响力。 山海鲸可视化&#xff1a;山海鲸可视化是一款强大…

Linux 常用命令记录

Linux(Ubuntu) 常用命令的总结 总结工作中用到的ubuntu命令&#xff0c;和添加一些常见的Linux的命令; 1.文件操作&常见命令操作 前置补充&#xff1a;Linux 终端提示符 && 命令语法 Centos[rootoldboy_python ~] ## [用户名主机机器名 路径] 提示符# 用户名 ro…

《计算机系统与网络安全》 第十章 防火墙技术

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

Three.js快速入门

Three.js快速入门 1、threejs文件包下载和目录简介 下载地址&#xff1a; 网盘链接:https://pan.baidu.com/s/1_Ix8TiOScypNcQe3BIl5vA?pwdrrks 提取码:rrksthreejs文件资源目录介绍 three.js-文件包 └───build——three.js相关库&#xff0c;可以引入你的.html文件中…

Frida遍历启动App所有Activity/Service

说明&#xff1a;仅供学习使用&#xff0c;请勿用于非法用途&#xff0c;若有侵权&#xff0c;请联系博主删除 作者&#xff1a;zhu6201976 一、需求 在一些大型App中&#xff0c;往往注册了大量的Activity和Service&#xff0c;这在App的AndroidManifest.xml文件可以清晰呈现。…

Centos7完整安装

一、前言 由于使用VMware workstation使用典型安装以及默认安装方式进行安装的Centos多存在组件不足的问题&#xff0c;这使得使用上述方式进行安装的系统在一些特定情况下需要安装组件&#xff0c;致使系统不是很便利&#xff0c;本文提供了在VMware workstation下进行完整安装…

Verdi之nTrace/nSchema

目录 3.nTrace介绍 3.1 启动Verdi 3.2查看Verdi中的设计结构 3.3查看Verdi中的验证结构 3.4 查找模块和trace信号 3.5 查找string 3.6 信号drive/load 3.7 快速查看设计有哪些信号 4 nSchema 4.1 如何打开原理图 4.2 如何查找 nShema window中器件的源码 4.3 如何显示原理…

【Java面试题】框架篇——Redis

文章目录 Redis的使用场景Redis支持的数据类型如何在Redis中实现分布式锁Redis和Mysql的事务有什么区别&#xff1f;Redis缓存穿透如何解决&#xff1f;Redis缓存雪崩如何解决&#xff1f;什么是缓存击穿&#xff0c;如何解决&#xff1f;Redis是单线程模式的&#xff0c;为什么…

chatgpt赋能python:Python超大数计算

Python超大数计算 介绍 在日常编程中&#xff0c;我们常常需要处理大量数据。这些数据可以是普通的整数或浮点数&#xff0c;但有时候我们需要计算的数据可能会超出计算机处理的数值范围。这时&#xff0c;我们需要使用更为高级的算法来进行超大数计算。 Python语言因为其简…

【Java】 Java 中处理 null 或缺失数据

本文仅供学习参考&#xff01; 相关教程地址&#xff1a; https://juejin.cn/post/7234924083842154556 https://cloud.tencent.com/developer/article/1107739?areaSource106005.3 https://www.developer.com/java/null-data-java/ 将某些内容表示为空白或不存在始终是编程中…

TX Text Control 31 sp3 for ActiveX-VB6-Crack

Visual Basic 6 应用程序的文档处理 适用于 Visual Basic 6 和基于 COM 的语言的综合文字处理和报告 视窗用户界面 功能齐全的文档编辑器 TX Text Control 是一款免版税、完全可编程的丰富编辑控件&#xff0c;它在专为 Visual Studio 设计的可重用组件中为开发人员提供了广泛的…