【数据结构】从链表到LinkedList类

在这里插入图片描述
🧧🧧🧧🧧🧧个人主页🎈🎈🎈🎈🎈
🧧🧧🧧🧧🧧数据结构专栏🎈🎈🎈🎈🎈
🧧🧧🧧🧧🧧上一篇文章:从顺序表到ArrayList类🎈🎈🎈🎈🎈

文章目录

  • 1.前言
    • 2.链表
    • 2.1 链表的概念及结构
    • 2.2链表的组合
    • 2.3链表的实现
    • 2.4LinkedList的模拟实现
      • 3.ArrayList和LinkedList的区别

1.前言

上一篇文章我们了解ArrayList表的使用,并且模拟了ArrayList表,通过数组的方式来存储数据单元。其底层是一块连续储存的空间,这时候我们发现当我们去插入数据或者删除数据的时候,需要将前后的数据整体向前移动或者向后移动。因此ArrayList是不能满足我们的需求。接下来我们可以来看看即将要学的LinkedList表。

2.链表

2.1 链表的概念及结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。结构像我们平时坐的交通工具火车一样,一节一节的,并不是按一定的顺序链接的,车厢可以随意链接,链表也是这样的。
在这里插入图片描述
在这里插入图片描述
注意:
1.从图中可以看出,链式结构不一定在物理上是连续的空间,但在逻辑上是连续的空间。
2.现实中的结点一般都是在堆上申请出来的。
3。在堆上申请的空间,是按定一定的规则来分配的,两次申请的空间可能是连续的空间,也有可能不是连续的空间。

2.2链表的组合

在现实当中有很多种的链表,有分单向和双向,带头和不带头,循环和不循环,总共有八种组合方式:
1.单向带头循环
在这里插入图片描述
2.单向带头不循环
在这里插入图片描述
3.单向不带头循环
在这里插入图片描述
4.单向不带头不循环
在这里插入图片描述
5.双向带头循环
在这里插入图片描述
6.双向带头不循环
在这里插入图片描述
7.双向不带头循环
在这里插入图片描述
8.双向不带头不循环
在这里插入图片描述
这么多种类型的链表,我们只了解两种单向不带头不循环和双向不带头不循环。
单向不带头不循环:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。
双向不带头不循环:在Java的集合框架库中LinkedList底层实现就是无头双向循环链表。

2.3链表的实现

2.3.1头插法

public void addFirst(int data) {
        ListNode node = new ListNode(data);
        //如果没有节点,直接将head标记放在要插的节点上,作为第一个首节点
        if(head == null) {
            this.head = node;
        }
        else {
            //先绑定,再移标记引用变量
            node.next = this.head;
            this.head = node;
        }
    }

2.3.2尾插法

public void addLast(int data) {
        ListNode node = new ListNode(data);
        //如果没有节点,直接将head标记放在要插的节点上,作为第一个尾节点
        if(head == null) {
            this.head = node;
        }
        else {
            ListNode cur = head;
            while(cur.next != null) {
                cur = cur.next;
            }
            cur.next = node;
        }

    }

2.3.3任意位置插入,第一个数据节点为0号下标

public void addIndex(int index, int data) {
        //判断index是否合法
        if(index < 0 || index > size()) {
            throw new IndexException("坐标"+index+":位置不合法");
        }
        ListNode node = new ListNode(data);
        //1.如果从头插入,直接头插法
        if(index == 0) {
            addFirst(data);
        }
        //2.从中间插
            ListNode cur = searchPrevIndex(index);
            node.next = cur.next;
            cur.next = node;
    }
    //创建一个找前驱的方法
    private ListNode searchPrevIndex(int index) {
        ListNode cur = head;
        int count = 0;
        while(count < index-1) {
            cur = cur.next;
            count++;
        }
        return cur;
    }

2.3.4查找是否包含关键字key是否在单链表当中

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

2.3.5删除第一次出现关键字为key的节点

public void remove(int key) {
        //删除头节点
        if(head.value == key) {
            head = head.next;
            return;
        }
        //1.找到要删除key的前驱
        ListNode cur = searchPrevKey(key);
        if(cur == null) {
            return;//没有你要删除的key
        }
        //2.定义一个标记curNext
        ListNode curNext = cur.next;
        //3.删除key
        cur.next = curNext.next;
    }
    private ListNode searchPrevKey(int key) {
        ListNode cur = head;
        while(cur.next != null) {
            if(cur.next.value == key) {
                return cur;
            }
            else {
                cur = cur.next;
            }
        }
        return null;
    }

2.3.6删除所有值为key的节点(非循环方法)

public void removeAllKeye(int key) {
        ListNode prev = head;
        ListNode cur = head.next;
        while (cur != null) {
            if(cur.value == key) {
                prev.next = cur.next;
                cur = cur.next;
            }else {
                prev = cur;
                cur = cur.next;
            }
        }
        //删除头节点
        if(head.value == key) {
            head = head.next;
        }
    }

2.3.7得到单链表的长度

public int size() {
        ListNode cur =head;
        int count = 0;
        while(cur != null) {
            cur = cur.next;
            count++;
        }
        return count;
    }

2.3.8清空链表

 public void clear() {
    head = null;
    }
}

2.4LinkedList的模拟实现

** 2.4。1头插法**

public void addFirst(int data) {
        ListNode node = new ListNode(data);
        //如果链表为空
        if(head == null) {
            head = node;
            last = node;
        }
        else {
            //链表不为空
            node.next = head;
            head.prev = node;
            node.prev = null;
            head = node;
        }
    }

** 2.4。2尾插法**

public void addLast(int data) {
        ListNode node = new ListNode(data);
        //如果链表为空
        if(head == null) {
            head = node;
            last = node;
        }
        else {
            //链表不为空
            last.next = node;
            node.prev = last;
            node.next = null;
            last = node;
        }
    }

** 2.4.3任意位置插入,第一个数据节点为0号下标**

public void addIndex(int index, int data) {
        //先判断index合不合法
        if(index<0 || index >size()) {
            throw new IndexException("位置不合法:"+index);
        }
        //1.从头插入,头插法
        if(index == 0) {
            addFirst(data);
            return;
        }
        //2.从尾插,尾插法
        if(index == size()) {
            addLast(data);
            return;
        }
        //3.从中间插
        //找要插入的位置
        ListNode cur = findAddIndex(index);
        ListNode node = new ListNode(data);
        node.next = cur;
        cur.prev.next = node;
        node.prev = cur.prev;
        cur.prev = node;
    }
    private ListNode findAddIndex(int index) {
        ListNode cur = head;
        while(index != 0) {
            cur = cur.next;
            index--;
        }
        return cur;
    }

** 2.4.4查找是否包含关键字key是否在单链表当中**

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

** 2.4.5删除第一次出现关键字为key的节点**

 public void remove(int key) {
        ListNode cur = head;
        while (cur != null) {
            if(cur.value == key) {
                if(cur == head) {
                    //删除头节点
                    head = head.next;
                    if(head != null) {
                        head.prev = null;
                    }else {
                        //只有一个节点 且是需要删除的节点
                        last = null;
                    }
                }else {
                    //删除中间节点
                    if(cur.next != null) {
                        cur.next.prev = cur.prev;
                        cur.prev.next = cur.next;
                    }else {
                        //删除尾巴节点
                        cur.prev.next = cur.next;
                        last = last.prev;
                    }
                }
                return;
            }
            cur = cur.next;
        }
    }

** 2.4.6删除所有值为key的节点**

 public void removeAllKeye(int key) {
        ListNode cur = head;
        while (cur != null) {
            if(cur.value == key) {
                if(cur == head) {
                    head = head.next;
                    if(head != null) {
                        head.prev = null;
                    }else {
                        //只有一个节点 且是需要删除的节点
                        last = null;
                    }
                }else {
                    //删除中间节点
                    if(cur.next != null) {
                        cur.next.prev = cur.prev;
                        cur.prev.next = cur.next;
                    }else {
                        //删除尾巴节点
                        cur.prev.next = cur.next;
                        last = last.prev;
                    }
                }
            }
            cur = cur.next;
        }
    }

** 2.4.7得到双链表的长度**

public int size() {
        ListNode cur = head;
        int count = 0;
        while(cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

** 2.4.8清除链表**

public void clear() {
    head =null;
    last =null;
    }

3.ArrayList和LinkedList的区别

在这里插入图片描述
结尾:
希望大家可以给我点点关注,点点赞,你们的支持就是我的最大鼓励。🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NerfStudio安装及第一个场景重建

NerfStudio文档是写在windows和linux上安装&#xff0c;本文记录Linux安装的过程&#xff0c;且我的cuda是11.7 创建环境 conda create --name nerfstudio -y python3.8 conda activate nerfstudio python -m pip install --upgrade pip Pytorch要求2.0.1之后的,文档推荐cud…

JavaWeb——005 请求响应 分层解耦(Postman、三层架构、IOC、DI、注解)

SpringBootWeb请求响应 这里写目录标题 SpringBootWeb请求响应前言1. 请求1.1 Postman1.1.1 介绍1.1.2 安装 1.2 简单参数1.2.1 原始方式1.2.2 SpringBoot方式1.2.3 参数名不一致 1.3 实体参数1.3.1 简单实体对象1.3.2 复杂实体对象 1.4 数组集合参数1.4.1 数组1.4.2 集合 1.5 …

产品老化试验目的、用途

什么是老化试验&#xff1f; 老化试验是通过模拟产品在使用过程中的老化情况&#xff0c;来评估产品在长期使用后的性能和可靠性。这种测试可以帮助制造商了解产品的寿命和耐久性&#xff0c;以及产品在不同环境条件下的表现。 模拟量采集/老化房采集软件 为什么需要进行老化试…

【Leetcode每日一刷】贪心算法01:455.分发饼干、376. 摆动序列、53. 最大子序和

博主简介&#xff1a;努力学习和进步中的的22级计科生博主主页&#xff1a; Yaoyao2024每日一句: “ 路虽远&#xff0c;行则将至。事虽难&#xff0c;做则可成。” 文章目录 前言&#xff1a;贪心算法一、455.分发饼干二、376. 摆动序列三、53. 最大子序和 前言&#xff1a;贪…

挑战杯 基于机器视觉的图像拼接算法

前言 图像拼接在实际的应用场景很广&#xff0c;比如无人机航拍&#xff0c;遥感图像等等&#xff0c;图像拼接是进一步做图像理解基础步骤&#xff0c;拼接效果的好坏直接影响接下来的工作&#xff0c;所以一个好的图像拼接算法非常重要。 再举一个身边的例子吧&#xff0c;…

信号系统之切比雪夫过滤器

1 切比雪夫和巴特沃斯的响应 切比雪夫响应是一种数学策略&#xff0c;通过允许频率响应中的纹波来实现更快的滚降。使用这种方法的模拟和数字滤波器称为切比雪夫滤波器。这些滤波器因使用切比雪夫多项式而得名&#xff0c;切比雪夫多项式由俄罗斯数学家帕夫努蒂切比雪夫&#…

基于FPGA的9/7整数小波变换和逆变换verilog实现,包含testbench

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 9/7整数小波变换原理 4.2 逆变换过程 5.算法完整程序工程 1.算法运行效果图预览 将测试结果导入到matlab显示 2.算法运行软件版本 vivado2019.2&#xff0c;matlab2022a 3.部分核心程…

寒假作业Day 01

这个项目主要是为了复习博主之前关于C语言和数据结构的寒假作业&#xff0c;大家也可以根据这些题目自己进行填写并检查自己的知识点是否过关 博主也会有错误&#xff0c;所以如果大家看到错误&#xff0c;也希望大家能够进行指正&#xff0c;谢谢大家&#xff01; Day 01 一…

静态链表(1)

什么叫静态链表&#xff1f;——用顺序表模拟链表&#xff0c;就叫做静态链表 第一列相当于数据域data&#xff0c;第二列相当于指针域next&#xff0c; 第一行&#xff08;0&#xff09;相当于头结点&#xff08;头结点的数据域不放数据&#xff09; &#xff08;a&#xff…

Rocky Linux安装部署Elasticsearch(ELK日志服务器)

一、Elasticsearch的简介 Elasticsearch是一个强大的开源搜索和分析引擎&#xff0c;可用于实时处理和查询大量数据。它具有高性能、可扩展性和分布式特性&#xff0c;支持全文搜索、聚合分析、地理空间搜索等功能&#xff0c;是构建实时应用和大规模数据分析平台的首选工具。 …

【C语言】while循环语句

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…

flask知识--01

flask介绍 # python 界的web框架&#xff1a; Django&#xff1a;大而全&#xff0c;使用率较高 &#xff1a;https://github.com/django/django -FastAPI&#xff1a;新项目选择使用它&#xff1a;https://github.com/tiangolo/fastapi -flask&#xff1a;公司一些…

【论文阅读】深度学习在过冷沸腾气泡动力学分割中的应用

Application of deep learning for segmentation of bubble dynamics in subcooled boiling 深度学习在过冷沸腾气泡动力学分割中的应用 期刊信息&#xff1a;International Journal of Multiphase Flow 2023 级别&#xff1a;EI检索 SCI升级版工程技术2区 SCI基础版工程技术3区…

探讨:围绕 props 阐述 React 通信

在 ✓ &#x1f1e8;&#x1f1f3; 开篇&#xff1a;通过 state 阐述 React 渲染 中&#xff0c;以 setInterval 为例&#xff0c;梳理了 React 渲染的相关内容。 &#x1f4e2; 本篇会 ✓ &#x1f1e8;&#x1f1f3; 围绕 props 阐述 React 通信 props React 组件使用 pro…

7.1 嵌入式软件设计资源管理-引言

1、简介 实时和嵌入式系统的一个显著特点是对有限资源的管理。这些资源可能是CPU时间、内存、网络带宽等&#xff0c;它们的有限性要求系统设计者必须精心管理以确保系统的高效运行。 1.1 资源管理 资源管理是实时和嵌入式系统设计中的一个核心问题&#xff0c;涉及CPU时间、…

三、软件-系统架构设计师笔记-计算机系统基础知识

计算机系统概述 计算机系统是指用于数据管理的计算机硬件、软件及网络组成的系统。 它是按人的要求接收和存储信息&#xff0c;自动进行数据处理和计算&#xff0c;并输出结果信息的机器系统。 冯诺依曼体系计算机结构&#xff1a; 1、计算机硬件组成 冯诺依曼计算机结构将…

kafka三节点集群平滑升级过程指导

一、前言 Apache Kafka作为常用的开源分布式流媒体平台&#xff0c;可以实时发布、订阅、存储和处理数据流,多用于作为消息队列获取实时数据&#xff0c;构建对数据流的变化进行实时反应的应用程序&#xff0c;已被数千家公司用于高性能数据管道、流分析、数据集成和任务关键型…

Keepalived双机热备——Haproxy搭建web群集

一、认识keepalived keepalived是一个开源的软件&#xff0c;用于实现高可用性和负载均衡。它主要用于在多个服务器之间提供故障转移和负载均衡的功能。keepalived可以监控服务器的状态&#xff0c;并在主服务器发生故障时自动将备份服务器切换为主服务器&#xff0c;以确保服…

统计分析笔记3

文章目录 统计检验选择正确的统计检验统计检验是做什么的&#xff1f;何时进行统计检验选择参数化测试&#xff1a;回归、比较或相关性选择非参数检验 假设检验的假设条件skewness什么是零偏度right skewleft skew计算skewnesswhat to do if your data is skewed kurtosis怎么计…

Python进阶学习:Pandas--将一种的数据类型转换为另一种类型(astype())

Python进阶学习&#xff1a;Pandas–将一种的数据类型转换为另一种类型(astype()) &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&…