数据结构-双链表思路解析及代码实现

news2025/1/18 8:46:03

双链表是单链表的进阶版,单链表是1-2-3-4 一个个排排坐链接,只管向后拉手,其主要思想是当前节点与下一节点的关系,那么双链表就多了一层关系,当前节点不仅和一下一点连起来,也要和上一节点串联起来。与前与后都要拉手。

如果对单链表不熟悉,建议先去看看单链表实现方式,链接如下

单链表实现代码以及解析

咱们还是先以定义节点开始,单链表是有当前节点和下一个节点的定义,那双向链表就需要有上一节点的定义,那就可以如下代码表现:

 public class DoubleLinked<E> {

    // 定义一个内部节点类
    private static class Node<E> {
        // 当前节点
        E item;
        // 上一节点
        Node<E> prev;
        // 下一节点
        Node<E> next;

        public Node(E item,  Node<E> prev,Node<E> next) {
            this.item = item;
            this.prev = prev;
            this.next = next;
        }
    }
}

1.添加节点

有了节点的定义就可以操作了,咱们先来添加操作

添加节点默认添加到尾部,所以调用linkLast方法,我们假如要添加1-2-3,我们要考虑添加了1以后,需要把2添加到1后,添加到3以后需要考虑2添加到3前等情况,咱们来逐个分析。

存储第一个节点时

1.我们需要实例化一个1的节点,因为不知道上一个节点值所以prev需要为空,也因为不知道下一个节点值所以next值需要为空,这样第一个值也就设置好了,那么设置好的值存储在哪里呢?才能把后面的值串连在一起,这时我们用全局变量first节点做这个事情

存储中间节点时

假设第一个节点存储好,那么添加第二个节点为2的值,操作又是什么?

当前节点为2的时候需要知道上一个节点值是1,下一个节点仍然不知道所以为空,所以构造方法就是 new Node(2,1,null),但是怎么知道上一个节点的值呢,这时候就需要添加个全局变量last,用来存储最后一个值,当第一个节点1存储进来时将1存储到last,第二个节点2过来的时候则直接用last也就是1就可, 用完后将last改为2,后面都以此种方式,就保证了last相比最新值时为上一个值。

    // 首值
    private Node first;
    // 最后值
    private Node last;
    private int size;

    public boolean add(E e) {
        linkLast(e);
        return true;
    }

    // 1-2-3
    void linkLast(E e) {
        // 上一个值,在第一次存储时为空
        Node l = last;
        // 新节点
        Node newNode = new Node(e, last, null);
        // 将新节点赋值给last
        last = newNode;
        // 第一次存储直接赋值给first即可
        if (l == null) {
            first = newNode;
        } else {
            // 通过引用类型的概念,此种方式则可让first串起来
            // 第二次及以后的值需要将上一个值的next设置为当前新的节点
            l.next = newNode;
        }
        size++;
    }

    // 打印链表数据
    private void printData() {
        Node f = null;
        for (int i = 0; i < size; i++) {
            if (i == 0) {
                System.out.print(first.item);
                f = first.next;
            } else {
                System.out.print("-" + f.item);
                f = f.next;
            }

        }
        System.out.println("");
    }
   public static void main(String[] args) {
        DoubleLinked doubleLinked = new DoubleLinked();
        doubleLinked.add("1");
        doubleLinked.add("2");
        doubleLinked.add("3");

        doubleLinked.printData();
        System.out.println("添加完毕-----------");
    }

 结果:

2.查询元素

根据小标索引查询链表数据,它这里用了将当前的链表长度除2,如果你要搜索的索引小于我计算过后的数字就证明你要找的位置比较靠前,所以就从头开始向后找(也就是说从first全局变量里循环取出next的数据),如果相反则证明你要找的数据在中后部分,需要从后向前找(也就是从last全局变量循环取出prev数据),还算蛮简单的哈。

  // 根据索引获取链表元素
 public E get(int index) {
     return node(index).item;
 }  

 Node<E> node(int index) {
        // 右移1位相当于除以2
        int i = size >> 1;
        // 如果要找的索引不大于i,则从前往后找最快
        if (index < i) {
            Node find = first;
            for (int i1 = 0; i1 < index; i1++) {
                find = find.next;
            }
            return find;
        } else {
            // 如果要找的索引大于i,则从后往前找更快
            Node find = last;
            for (int i1 = size - 1; i1 > index; i1--) {
                find = find.prev;
            }
            return find;
        }
    }

 3.删除

删除节点,毋庸置疑我们要移动前后节点,挤出待删除节点。

待删除为中间节点的话:

 比如1-2-3-4-5 我需要将2删除,索引就是1,需要将2的前一个节点也就是1找到,然后将1的下一个节点改为3,将2的下一个节点3找到,将3的上一个节点改为1,这样2的这个节点自然就删除了,这是删除中间的链表

待删除是头节点第一个的话:

假如1-2-3-4-5 删除的是1,索引就是0,此时1的节点上一个是空,这时需要找到当前节点的下一个节点直接赋值头节点即可。

待删除是最后一个节点的话:

假如1-2-3-4-5 删除的是5,索引就是4,此时下一个节点就是空,这时需要找到当前节点的上一个节点置为空即可。

    // 1-2-3-4-5
    public boolean remove(int index) {
        // 得到待删除的节点
        Node node = node(index);
        // 得到删除的节点前一个节点
        Node prev = node.prev;
        // 得到删除的节点后一个节点
        Node next = node.next;
        // 当前节点前一个为空,则证明要删除第一个,直接将当前值下一个节点覆盖first即可
        if (prev == null) {
            first = next;
        } else {
            // 给上一个节点的next节点改成当前节点的下一个
            prev.next = next;
            if (next != null) {
                // 给下一个节点的prev节点改成当前节点的上一个
                next.prev = prev;
            }
        }
        size--;
        return true;
    }
public static void main(String[] args) {
        DoubleLinked doubleLinked = new DoubleLinked();
        doubleLinked.add("1");
        doubleLinked.add("2");
        doubleLinked.add("3");
        doubleLinked.add("4");
        doubleLinked.add("5");

        doubleLinked.printData();
        System.out.println("添加完毕-----------");

        System.out.println("查找元素2:" + doubleLinked.get(1));
        System.out.println("查找元素1:" + doubleLinked.get(0));
        System.out.println("查找元素3:" + doubleLinked.get(2));


        System.out.println("删除2:" + doubleLinked.remove(1));
        System.out.println("删除3:" + doubleLinked.remove(1));
        System.out.println("删除1:" + doubleLinked.remove(0));
        doubleLinked.printData();

    }

 

 

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

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

相关文章

【全志T113-S3_100ask】13-1 Linux c语言ioctl驱动oled(iic、ssd1306)屏幕

【全志T113-S3_100ask】13-1 Linux C通过ioctl驱动oled[ssd1306]屏幕 背景&#xff08;一&#xff09;i2c关键结构体1、i2c_rdwr_ioctl_data结构体2、struct i2c_msg结构体&#xff08;二&#xff09;i2c关键代码1、写函数2、读函数&#xff08;三&#xff09;对oled的操作&…

深度学习和神经网络的介绍(一)

1、深度学习和神经网络 1.1 深度学习的介绍 目标&#xff1a; 知道什么是深度学习知道深度学习和机器学习的区别能够说出深度学习的主要应用场景知道深度学习的常见框架 1.1.1 深度学习的概念 深度学习是机器学习的分支&#xff0c;是一种以人工神经网络为架构&#xff0c…

计算机网络4小时速成:计算机网络基础,计网组成,计网分类,性能指标,标准化组织,计网结构模型,五层模型

计算机网络4小时速成&#xff1a;计算机网络基础&#xff0c;计网组成&#xff0c;计网分类&#xff0c;性能指标&#xff0c;标准化组织&#xff0c;计网结构模型&#xff0c;五层模型 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&…

05_TCP并发服务器

知识点1【TCP并发服务器】 1、多线程&#xff08;常用&#xff09; 2、解决上述问题&#xff1a;端口复用 仅仅是端口的复用 3、并发服务器 多进程实现 总结&#xff1a; 知识点2【HTTP协议】 HTTP基于TCP 1、HTTP协议的概述 2、Webserver 通信过程 3、Web编程开发 知识…

Cadence orcad 批量设置原理图标题栏

前言 作为一份规范的原理图文件&#xff0c;必须要有Title Block&#xff0c;一般是在右下角的原理图信息&#xff0c;包括标题&#xff0c;图纸尺寸&#xff0c;设计师&#xff0c;时间&#xff0c;页码等等。 这里需要两个操作&#xff1a; 一、批量修改Title Block的信息 …

Go语言进阶篇,单元测试、基准测试的性能测试、内存占用测试

在go语言中的单元测试比较有意思&#xff0c;比如测试一个函数是很方便的&#xff0c;只需要将文件名修改为_test.go这样的后缀即可&#xff0c;我们新建一个目录xxx&#xff0c;然后新建xxx_test.go文件&#xff0c;当然这个xxx的名字你可以按照功能来命名&#xff0c;如下&am…

Java开发:多线程编程

本章篇幅主要记录多线程编程相关的知识&#xff0c;如有纰漏&#xff0c;望指出。 话不多说&#xff0c;正式开启多线程之旅... 目录 一、多线程使用方式 A、Thread B、Runnable&#xff08;推荐&#xff09; C、Callable 二、线程的五个状态 三、线程停止 四、线程休…

LabVIEW性能和内存管理 7 LabVIEW中局部和全局变量的内存分配

LabVIEW性能和内存管理 7 LabVIEW中局部和全局变量的内存分配 本文介绍LabVIEW性能和内存管理的几个建议7。 LabVIEW Cleanup – LabVIEW cleans upmany references when the owning VI goes idle and others when the process closes – Manually closereferences t…

Bean的作用域和生命周期

1. Bean 的作用域 对于全局变量,局部变量等的作用域相信大家都已经很清楚了,但是对于对象作用域有点摸不着头脑,下面通过一个简单的案例,康康对象的作用域 1.1 案例引入 现有一个公共的 Bean 对象 package com.bean.model;import org.springframework.stereotype.Componen…

【IEEE2017】RL:机器人库:一种面向对象的机器人应用程序的方法

RL&#xff1a;机器人库&#xff1a;一种面向对象的机器人应用程序的方法 摘要&#xff1a; 摘要&#xff1a;我们讨论了机器人库&#xff08;RL&#xff09;的架构和软件工程原理。在机器人系统、研究项目、工业应用和教育的需求的驱动下&#xff0c;我们确定了相关的设计需求…

linux上如何搭建Java环境

一 linux软件安装常用的方式对比 Linux下的软件安装&#xff0c;主要有如下三种&#xff0c;“正规”程度依次递减&#xff1a; 1、使用标准的yum/apt/yast包管理程序安装 2、使用标准rpm/deb或厂商自己的安装包&#xff08;比如nVidia的显卡驱动用的bin包&#xff09;安装 …

黑*头条_第2章_文章列表前端成形与后端变身

黑*头条_第2章_文章列表前端成形与后端变身 文章目录黑*头条_第2章_文章列表前端成形与后端变身文章列表前端成形与后端变身学习目标1.前端工程结构1.1 环境准备1.1.1 导入工程1.1.2 测试运行1.2 weex 跨终端前端框架1.3 工程结构说明1.4 源码结构1.5 WEEX UI2.文章列表前端开发…

算法实验题(涉外黄成老师!!!)

日期 2022.11.19 目录 实验报告一 第一题 2 实验报告二 第二题 3 实验报告三 第三题 4 实验报告四 第四题 5 实验报告五 第五题 6 实验报告六 第六题 7 实验报告一 第一题 一、实验目的 由1&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;7&#xff0c;8这六个数字所组…

剑指 Offer II 021. 删除链表的倒数第 n 个结点【链表】

难度等级&#xff1a;中等 上一篇算法&#xff1a; 82. 删除排序链表中的重复元素 II【链表】 力扣此题地址&#xff1a; 剑指 Offer II 021. 删除链表的倒数第 n 个结点 - 力扣&#xff08;LeetCode&#xff09; 1.题目&#xff1a;删除链表的倒数第 n 个结点 给定一个链表&a…

DWGViewX Pro 2021.4.X Crack by Cracki

DWGViewX pro 2021.4.X --Ω578867473 DWGViewX 是一个 ActiveX 组件&#xff0c;可让您在一个查看器中管理和查看 DWG、DXF 和 DWF 工程图。查看 R14 到 2022 版本的 DWG、DXF 和 DWF。加载本地磁盘或网络网站上的图纸&#xff0c;并使用查看器缩放、平移、旋转图纸、打开/关闭…

Java中的线程

线程 什么是线程&#xff1a; 什么是多线程&#xff1a; 学习目的&#xff1a; 多线程的创建 方式一&#xff1a;继承Thread类 public class MyThread{public static void main(String[] args) {Thread thread01 new Thread01();thread01.start();for (int i 0; i < 5; …

翻倍增长!C-V2X商业化“提速”,新一代模组加速“助跑”

C-V2X正在逐步走向商业的规模化部署&#xff0c;由此也带动了C-V2X模组需求的高速增长。 高工智能汽车研究院监测数据显示&#xff0c;今年1-9月中国市场&#xff08;不含进出口&#xff09;乘用车前装标配搭载V2X技术新车交付上险为10.58万辆&#xff0c;同比增长283.33%&…

计算机视觉|投影与三维视觉

这一篇将学习投影与三维视觉&#xff0c;沿用上一篇 计算机视觉|针孔成像&#xff0c;相机内外参及相机标定&#xff0c;矫正的重要性 摄像机内参数矩阵M、畸变参数、旋转矩阵R、平移向量T以及但影响矩阵H。回顾放射和投影变换&#xff0c;并使用POSIT算法从一幅图像中查找获得…

基于stm32单片机有害气体监测检测Proteus仿真

资料编号&#xff1a;097 下面是相关功能视频演示&#xff1a; 97-基于stm32单片机有害气体监测检测Proteus仿真&#xff08;仿真源码全套资料&#xff09;功能介绍&#xff1a;检测当前的有害气体浓度&#xff0c;LCD1602显示&#xff0c;并且可以自动打开关闭风扇&#xff…

Pulsar 各个Shedder分析及新的Shedder -- AvgShedder

看到今年Pulsar 峰会上挺多人分享负载均衡的内容&#xff0c;这里也整理分享一下相关的内容。 社区现有策略的分析 LoadSheddingStrategy pulsar进行shedding的时候&#xff0c;使用的是ThresholdShedder类&#xff0c;ThresholdShedder类是LoadSheddingStrategy接口的其中一…