目录

LinkedList的模拟实现

什么是双向链表

增加数据

头插法:

 尾插法:

指定的下标插入:

删除数据

 删除双向链表中出现的第一个key

置空所有数据

LinkedList和ArrayList的区别


        

顺序表对应的集合类是ArrayList;链表对应的集合类是LinkedList,在Java集合框架中,它们是两种最基础也是最常用的数据结构实现,它们的底层实现原理和性能差异是怎么样的呢?这里我们先来模拟实现LinkedList;

LinkedList的模拟实现

什么是双向链表

        首先,我们要知道的是LinkedList的底层使用了双向链表,那么什么是双链表呢?我们前面学过单链表是由一个个节点组成,节点中包括数据域和指针域的一个链表其中指针域存放着下一个节点的地址值:

        双向链表同样也是由一个个节点组成,多了个prev指针,指向前驱节点的地址,和一个last指针指向最后一个节点;那么我们如何构建一个双向链表呢?基于单链表的学习,双向链表我们模仿单链表的样式去写就简单很多了:

    //1.想构成链表的是?->节点由什么组成?定义变量 一个节点为一个对象定义成内部类static class ListNode{public int val;public ListNode next;public ListNode prev;//构造一个节点,只需要实例化public ListNode(int val) {this.val = val;}}//指向节点的一些指针public ListNode head;public ListNode last;//始终指向最后一个节点

         这样写好一个链表的基本结构我们就可以为这个链表写一些操作方法了;双向链表有一些操作时不太涉及prev指针域的,这些操作是跟前面学习的单链表一致的,比如:链表打印display、表长size、查找链表的元素contains、这里就不重复记录了;具体看单链表的手动实现+相关习题,这里主要介绍与单链表有点区别的操作。

增加数据

头插法:

    public void addFirst(int data) {//1.实例化一个节点ListNode node = new ListNode(data);//2.链表尾空if (head == null){head = node;last = node;}else {node.next = head;//先绑定后面head.prev = node;head = node;}return;}

双向链表中有两个指针域,操作节点是要尤其注意操作指针域的顺序,要避免数据丢失的情况。 

 尾插法:

    public void addLast(int data) {ListNode node = new ListNode(data);if (head == null){head = node;last = node;}else {last.next = node;node.prev = last;last = node;//注意要更新last节点,保证last是最后一个节点}}

指定的下标插入:

        在指定下标位置进行插入时,我们重点要关注的是中间插入元素是的操作顺序

    public void addIndex(int index, int data) {ListNode node = new ListNode(data);//1.判断index合法性if (index < 0 && index > size()){throw new IndexException("index非法" + index);}//2.index为0时,头插if (index == 0){addFirst(data);return;}//index为size时,尾插if (index == size()){addLast(data);return;}//3.找indexListNode cur = findIndex(index);//注意顺序node.next = cur;cur.prev.next = node;node.prev = cur.prev;cur.prev = node;}private ListNode findIndex(int index){ListNode cur = head;int count = 0;while (count != index){//因为是双向链表,可以访问到节点的前驱和后继,所以不用跟单链表一样找index-1cur = cur.next;count++;}return cur;}

删除数据

 删除双向链表中出现的第一个key

注意:删除时要考虑到所有特殊的情况,比如删除头结点、尾结点、链表只有一个节点的情况:

    public void remove(int key) {//遍历找keyListNode cur = head;while (cur != null){if (cur.val == key ){//1.要删的节点是头结点if (cur == head){head = head.next;if (head != null){head.prev = null;}else {//链表只有一个节点且是需要删除的节点,也得置空last = null;}return;}else {if (cur.next == null){//删除尾结点cur.prev.next = null;last = last.prev;}else {//删除中间节点cur.prev.next = cur.next;cur.next.prev = cur.prev;}}return;}cur = cur.next;}}

        删除第一个key值得代码我们写出来了,那么删除所有key值也非常得简单了,把return去掉让他继续往下遍历往下删除即可;

置空所有数据

        我们可以直接简单粗暴的分别把head和last置空,导致整个表置空;也可以把每个节点的指针域依次置空 ,本质上两种方法时一样的:

    public void clear() {//循环把节点依次置空ListNode cur = head;while (cur != null){//定义一个指针指向即将被删除的节点,记录下下一个要被删除的节点ListNode curNext = cur.next;cur.prev = null;cur.next = null;cur = curNext;}this.head = null;this.last = null;}

LinkedList和ArrayList的区别

存储空间方面:

  • ArrayList物理存储和逻辑顺序都是连续的(基于动态数组实现)。

  • LinkedList逻辑上是连续的,但物理存储不一定连续(基于双向链表实现)。

查找修改效率:

  • ArrayList是数组结构,支持随机访问,可以直接通过索引定位元素,效率极高O(1);修改的第一步也是要访问,所以修改的时间复杂度也为O(1)

  • LinkedList不支持随机存取,必须从头或尾遍历链表,访问效率较低O(n)

插入和删除元素效率:

  • ArrayList 插入或删除除了头节点和尾结点元素时,需要移动后续所有元素,效率较低O(n)

  • LinkedList只需调整相邻节点的指针,无需移动数据,效率更高O(1)

扩容机制:

  • ArrayList:采用静态分配,初始容量固定,扩容时需要重新分配更大的数组并复制数据,时间复杂度 O(n)。可能导致空间浪费或频繁扩容。

  • LinkedList:动态分配,每次插入新元素时才分配内存,无需扩容。没有容量限制,但每个节点需要额外存储指针,占用更多内存。

适用场景:

  • ArrayList:适合读多写少的场景,。

  • LinkedList:适合增删频繁的场景。


 感谢大家阅读📚点赞👍收藏⭐评论✍关注❤

博客主页: 【长毛女士-CSDN博客 

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue + WebSocket 实时数据可视化实战:多源融合与模拟数据双模式设计

在现代交通大屏项目中&#xff0c;实时数据的采集和可视化尤为重要。本文结合 Vue3 和 ECharts&#xff0c;分享一个支持多 WebSocket 数据源实时合并、模拟数据调试、自动重连的完整设计方案&#xff0c;帮助你快速搭建健壮的数据可视化组件。一、项目背景与核心需求实时接收多…

C#索引器、接口、泛型

以下是对提供的 C# 代码中涉及的核心知识点的梳理和总结&#xff0c;涵盖索引器、接口、泛型三大核心内容&#xff0c;以及相关实践要点&#xff1a;一、索引器&#xff08;Indexer&#xff09;索引器是一种允许类或结构体像数组一样通过[]语法访问成员的特殊成员&#xff0c;本…

界面组件DevExpress WPF中文教程:Grid - 如何过滤节点?

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

Excel——INDEX和MATCH傻傻分不清?

核心逻辑​先用 MATCH 找到目标姓名在表格中的 ​行号&#xff0c;再用 INDEX 根据行号 ​提取对应信息。就像查字典&#xff1a;先用拼音找到字的页码&#xff08;MATCH 找行号&#xff09;再翻到该页看具体解释&#xff08;INDEX 取数据&#xff09;​分步拆解&#xff08;以…

制造业低代码平台实战评测:简道云、钉钉宜搭、华为云Astro、金蝶云·苍穹、斑斑低代码,谁更值得选?

上回聊了斑斑和简道云&#xff0c;不少同行私信问我其他几个低代码平台怎么样&#xff0c;今天就给大家来个"五大门派"终极对决&#xff01; 一、先说痛点 制造业搞数字化最怕三件事&#xff1a; 1.钱花了没效果&#xff08;大平台用不起&#xff0c;小工具不够用&…

Jenkins中HTML文件显示样式问题解决方案

Jenkins中HTML文件显示样式问题解决方案 问题描述 在Jenkins中归档的HTML文件显示格式失效&#xff0c;样式无法正常显示&#xff0c;但在本地浏览器中打开却能正常显示。 问题原因 Jenkins为了安全考虑&#xff0c;默认设置了严格的内容安全策略(Content Security Policy, CSP…

四、配置文件

文章目录1. 文件类型1.1 properties1.2 yaml1.2.1 简介1.2.2 基本语法1.2.3 数据类型1.2.4 示例2. 配置提示1. 文件类型 1.1 properties 同以前的properties的用法 1.2 yaml 1.2.1 简介 YAML 是 “YAML Ain’t Markup Language”&#xff08;YAML 不是一种标记语言&#x…

Python常用医疗AI库以及案例解析(场景化进阶版)

📊 框架应用拓扑图用例 #mermaid-svg-lZ1J5KCaVWBV2kAu {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-lZ1J5KCaVWBV2kAu .error-icon{fill:#552222;}#mermaid-svg-lZ1J5KCaVWBV2kAu .error-text{fill:#552222;st…

Python高效操作Kafka实战指南

Python操作Kafka的高效 以下是使用Python操作Kafka的高效消息发送实例,涵盖基础发送、批量处理、异步回调等场景。示例基于confluent-kafka库(推荐)和kafka-python库,代码均经过实测。 流程图 基础消息发送(同步) from confluent_kafka import Producerproducer = Pro…

离线快速处理PDF格式转化的方案

日常办公中&#xff0c;PDF 几乎成了我们离不开的文件格式。然而像 WPS 这样的工具&#xff0c;不少实用功能都需要额外付费才能解锁。它的打开方式很简单&#xff0c;双击桌面图标即可运行。它不会弹出主界面&#xff0c;而是默默驻留在系统托盘区&#xff0c;需要时双击图标就…

SpringMVC注解与SpringCloudOpenFeign注解对比

1. 背景知识 梳理SpringMVC和SpringCloudOpenFeign常用注解后&#xff1a; Spring MVC中常用注解_笔记-CSDN博客Spring Cloud OpenFeign 常用注解_笔记-CSDN博客 这里对两类注解做个对比。理解两者定位&#xff08;服务端 vs 客户端&#xff09;是掌握注解使用的关键&#x…

Linux 时间同步的流程

一、问题时间RTC时间、系统时间(UTC)和本地时间的关系如下&#xff1a;‌RTC时间‌&#xff08;硬件时钟&#xff09;&#xff1a;显示为UTC时间格式&#xff1a;02:50:35/02:51:28由主板电池供电&#xff0c;独立于系统运行‌12通常存储UTC时间&#xff08;Linux默认配置&…

VSCode——python选择解释器消失的解决办法

VSCode软件的左下角 设置——检查更新&#xff1a;

笛卡尔积规避:JOIN条件完整性检查要点

笛卡尔积是数据库查询中的高风险操作&#xff0c;多表JOIN时缺失有效关联条件会导致结果集指数级膨胀&#xff0c;引发‌性能塌方‌甚至系统崩溃‌。以下是核心检查策略及防御方案&#xff1a;一、笛卡尔积的致命影响‌‌性能塌方‌百万级订单表与千万级用户表缺失ON条件时&…

Vimba相机二次开发教程,基于Python

文章目录安装获取图像辅助数据Vimba 是由 Allied Vision 开发的一套软件开发套件&#xff08;SDK&#xff09;&#xff0c;主要用于控制和操作其工业相机产品。它提供了一套完整的 API 和工具&#xff0c;支持多种操作系统和编程语言&#xff0c;便于开发者快速集成相机功能到应…

电子测试行业软件ATECLOUD与ETEST对比分析-纳米软件

在当今科技飞速发展的时代&#xff0c;电测行业对于自动化测试平台的依赖程度日益加深。高效、精准的自动化测试平台不仅能够提升测试效率&#xff0c;还能确保产品质量。ATECLOUD 与 ETEST 作为电测行业中颇受瞩目的自动化测试平台&#xff0c;各自展现出独特的优势与特点。下…

自动化测试中的常见测试方法

自动化测试中的常见测试方法在自动化测试中&#xff0c;除了数据驱动&#xff08;Data-Driven Testing&#xff09;&#xff0c;还有多种主流方法&#xff0c;每种方法适用于不同场景和需求。以下是常见的自动化测试方法分类及详解&#xff1a;一、关键字驱动测试&#xff08;K…

口语01-don‘t judge a book by its cover

Dont judge a book by its cover 不要以貌取人1 the most advanced thing2 stack3 right4 frantically5 be annoyed with sb6 Get your stuff off my desk7 But today I came to class and was running a few minutes late.8 take my seat&#xff1a;占我座位 / 坐我的位置9 s…

《Uniapp-Vue 3-TS 实战开发》自定义预约时间段组件

这个组件可以直接在 uniapp 项目中使用,提供了 24 小时时段选择功能,支持单选 / 多选、预设时段选择、随机选择等功能。 html版本: <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="vi…

《Uniapp-Vue 3-TS 实战开发》自定义环形进度条组件

引言 在UniApp中使用Vue3和TypeScript开发环形进度条组件,我们可以考虑三种技术:Canvas、SVG和纯HTML(利用CSS)。考虑到兼容性、实现难度和效果,SVG是较好的选择。它可以轻松实现环形进度条,支持渐变色,并且可以通过属性精确控制进度,同时在不同分辨率屏幕上清晰显示…