引言

链表作为基础数据结构之一,在Java集合框架中以LinkedList的形式提供。本文将深入分析Java原生LinkedList的实现机制,并介绍我自定义实现的MyLinkedList,最后对比两者的设计差异与实现特点。

Java原生LinkedList解析

基本结构

Java的LinkedList是基于双向链表实现的列表,主要特点包括:

  1. 双向链表结构:每个节点包含前驱和后继指针

  2. 高效端点操作:头尾插入/删除时间复杂度为O(1)

  3. 队列功能:实现了Deque接口,支持队列操作

核心实现机制

// JDK中的关键字段
transient int size = 0;
transient Node<E> first; // 头节点
transient Node<E> last;  // 尾节点// 节点定义
private static class Node<E> {E item;Node<E> next;Node<E> prev;Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}
}

插入操作示例

void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;size++;
}

时间复杂度分析

  • 头尾插入/删除:O(1)

  • 按索引访问:平均O(n/2)

  • 中间插入/删除:O(n)(需要先定位节点)

自定义MyLinkedList实现

package com.zsy;import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;/*** 自定义双向链表实现,支持泛型元素存储和基本列表操作** <p>本实现提供类似Java LinkedList的核心功能,包括:</p>* <ul>*   <li>基于节点的双向链表结构</li>*   <li>支持头部和尾部高效操作</li>*   <li>提供元素遍历功能</li>*   <li>实现基本的增删改查操作</li>* </ul>** <p><b>特性说明:</b></p>* <ul>*   <li>时间复杂度:访问O(n),头尾操作O(1)</li>*   <li>空间复杂度:O(n)</li>*   <li><b>非线程安全</b> - 多线程环境下需要外部同步</li>* </ul>** @param <E> 列表元素类型* @author zsy* @see List*/
public class MyLinkedList<E> implements List<E> {/*** 当前列表中元素的数量*/private int size;/*** 链表头节点*/private Node<E> head;/*** 链表尾节点*/private Node<E> tail;/*** 将指定元素追加到列表末尾** @param element 要添加的元素*/@Overridepublic void add(E element) {Node<E> newNode = new Node<>(tail, element, null);if (tail != null) {tail.next = newNode;} else {head = newNode;}tail = newNode;size++;}/*** 在列表的指定位置插入指定元素** @param element 要插入的元素* @param index 插入位置的索引* @throws IndexOutOfBoundsException 如果索引超出范围*/@Overridepublic void add(E element, int index) {rangeCheckForAdd(index);if (index == size) {add(element);return;}Node<E> target = getNode(index);Node<E> prev = target.pre;Node<E> newNode = new Node<>(prev, element, target);if (prev == null) {head = newNode;} else {prev.next = newNode;}target.pre = newNode;size++;}/*** 移除并返回列表中指定位置的元素** @param index 要移除元素的索引* @return 被移除的元素* @throws IndexOutOfBoundsException 如果索引超出范围*/@Overridepublic E remove(int index) {rangeCheck(index);return unlink(getNode(index));}/*** 从列表中移除首次出现的指定元素** @param element 要移除的元素* @return 如果列表包含该元素则返回true*/@Overridepublic boolean remove(E element) {for (Node<E> x = head; x != null; x = x.next) {if (Objects.equals(element, x.value)) {unlink(x);return true;}}return false;}/*** 替换列表中指定位置的元素** @param index 要替换元素的索引* @param element 要存储的元素* @return 先前在指定位置的元素* @throws IndexOutOfBoundsException 如果索引超出范围*/@Overridepublic E set(int index, E element) {rangeCheck(index);Node<E> node = getNode(index);E oldVal = node.value;node.value = element;return oldVal;}/*** 返回列表中指定位置的元素** @param index 要返回元素的索引* @return 列表中指定位置的元素* @throws IndexOutOfBoundsException 如果索引超出范围*/@Overridepublic E get(int index) {rangeCheck(index);return getNode(index).value;}/*** 返回列表中的元素数量** @return 列表中的元素数量*/@Overridepublic int size() {return size;}/*** 返回此列表中元素的迭代器** @return 按适当顺序包含此列表中所有元素的迭代器*/@Overridepublic Iterator<E> iterator() {return new LinkedListIterator();}// ========== 私有辅助方法 ==========/*** 获取指定索引处的节点*/private Node<E> getNode(int index) {if (index < (size >> 1)) {Node<E> x = head;for (int i = 0; i < index; i++)x = x.next;return x;} else {Node<E> x = tail;for (int i = size - 1; i > index; i--)x = x.pre;return x;}}/*** 从链表中移除指定节点*/private E unlink(Node<E> node) {final E element = node.value;final Node<E> next = node.next;final Node<E> prev = node.pre;if (prev == null) {head = next;} else {prev.next = next;node.pre = null;}if (next == null) {tail = prev;} else {next.pre = prev;node.next = null;}node.value = null;size--;return element;}/*** 检查索引是否在有效范围内*/private void rangeCheck(int index) {if (index < 0 || index >= size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}/*** 检查添加操作的索引是否在有效范围内*/private void rangeCheckForAdd(int index) {if (index < 0 || index > size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}/*** 构造索引越界异常信息*/private String outOfBoundsMsg(int index) {return "Index: "+index+", Size: "+size;}// ========== 内部类实现 ==========/*** 双向链表节点实现*/private static class Node<E> {/*** 前驱节点*/Node<E> pre;/*** 后继节点*/Node<E> next;/*** 节点存储的值*/E value;Node(Node<E> pre, E value, Node<E> next) {this.pre = pre;this.value = value;this.next = next;}}/*** 链表迭代器实现*/private class LinkedListIterator implements Iterator<E> {/*** 当前迭代节点*/private Node<E> current = head;/*** 检查是否还有更多元素可迭代** @return 如果迭代有更多元素则返回true*/@Overridepublic boolean hasNext() {return current != null;}/*** 返回迭代中的下一个元素** @return 迭代中的下一个元素* @throws NoSuchElementException 如果迭代没有更多元素*/@Overridepublic E next() {if (!hasNext())throw new NoSuchElementException();E element = current.value;current = current.next;return element;}}
}

性能考虑

双向链表与数组列表的性能对比:

操作ArrayListLinkedList
随机访问O(1)O(n)
头部插入/删除O(n)O(1)
尾部插入/删除平均O(1)O(1)
中间插入/删除O(n)O(n)
内存占用更紧凑每个元素额外占用空间

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

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

相关文章

【深度学习】卷积神经网络(CNN):计算机视觉的革命性引擎

卷积神经网络&#xff08;CNN&#xff09;&#xff1a;计算机视觉的革命性引擎 一、算法背景&#xff1a;视觉智能的进化之路1.1 传统视觉处理的困境1.2 神经科学的启示 二、算法理论&#xff1a;CNN的核心架构2.1 基础组成单元卷积层&#xff1a;特征提取引擎池化层&#xff1…

使用@SpringJUnitConfig注解开发遇到的空指针问题

Spring测试中的版本陷阱&#xff1a;SpringJUnitConfig与JUnit版本兼容性深度解析 一个看似简单的空指针异常&#xff0c;背后可能隐藏着JUnit版本不匹配的“幽灵”。 一、SpringJUnitConfig&#xff1a;Spring与JUnit 5的桥梁 SpringJUnitConfig是Spring TestContext框架为**…

[2025CVPR]AdcSR:一种高效实世界图像超分辨率的对抗扩散压缩方法

目录 1. 背景与挑战 2. AdcSR模型概述 2.1 模型架构 2.2 训练策略 3. 公式与原理 4. 创新点 5. 实验与结果 5.1 实验设置 5.2 结果对比 5.3 消融实验 6. 结论 在计算机视觉领域&#xff0c;图像超分辨率&#xff08;Image Super-Resolution, ISR&#xff09;一直是一…

Go 语言中的字符串基本操作

这篇文章已经放到腾讯智能工作台的知识库啦&#xff0c;链接在这里&#xff1a;ima.copilot-Go 入门到入土。要是你有啥不懂的地方&#xff0c;就去知识库找 AI 聊一聊吧。 本篇将详细讲解 Go 语言中与字符串相关的操作。 1、rune 和 字符串长度 1、Go 函数语法约定 在开始…

数学建模会议笔记

看似优化模型 建立整数规划模型 用优化软件、启发式方法、精确方法求解 建立图论和组合优化模型用组合优化方法、启发式方法求解 建立博弈论模型 数据统计分析与可视化- 数据拟合、参数估计、插值、数据的标准化、去伪补全相关度分析、分类、聚类等 最优化理论和方法 线性规划…

学习昇腾开发的六天--ACL应用开发之运行第一个实例

1、下载一个实例&#xff0c;运行一个图像分类实例&#xff08;环境&#xff1a;Ubuntu22.04&#xff0c;硬件&#xff1a;昇腾310B1&#xff0c;加速模块&#xff1a;atlas 200i a2&#xff09; samples: CANN Samples - Gitee.com 目录结构如下&#xff1a; ├── data │…

可灵AI-快手公司自主研发的一款AI视频与图像生成工具

可灵AI是由快手公司自主研发的一款AI视频与图像生成工具&#xff0c;于2024年6月正式推出。以下是对其的详细介绍&#xff1a; 核心功能 AI视频生成&#xff1a; 文生视频&#xff1a;输入文字描述&#xff0c;AI可自动生成匹配的视频片段。图生视频&#xff1a;上传图片&…

创客匠人解析:存量时代创始人 IP 打造与免费流量池策略

在存量竞争的商业环境中&#xff0c;企业如何突破增长瓶颈&#xff1f;创客匠人结合新潮传媒创始人张继学的实战洞察&#xff0c;揭示 “品牌 IP” 双轮驱动下的免费流量池构建逻辑&#xff0c;为知识变现与创始人 IP 打造提供新思路。 一、存量时代的流量革命&#xff1a;从…

提升语义搜索效率:LangChain 与 Milvus 的混合搜索实战

我从不幻想人生能够毫无波折&#xff0c;但我期望遭遇困境之际&#xff0c;自身能够成为它的克星。 概述 LangChain与Milvus的结合构建了一套高效的语义搜索系统。LangChain负责处理多模态数据&#xff08;如文本、PDF等&#xff09;的嵌入生成与任务编排&#xff0c;Milvus作…

MySQL配置简单优化与读写测试

测试方法 先使用sysbench对默认配置的MySQL单节点进行压测&#xff0c;单表数据量为100万&#xff0c;数据库总数据量为2000万&#xff0c;每次压测300秒。 sysbench --db-drivermysql --time300 --threads10 --report-interval1 \--mysql-host192.168.0.10 --mysql-port3306…

猎板深耕透明 PCB,解锁电子设计新边界

在电子技术快速迭代的当下&#xff0c;猎板始终关注行业前沿&#xff0c;透明 PCB 作为极具创新性的技术&#xff0c;正在改变电子设备的设计与应用格局。​ 从传统的绿色、棕色 PCB 到如今的透明 PCB&#xff0c;其突破在于特殊基材与导电材料的运用&#xff0c;实现 85%-92%…

FLAML:快速轻量级自动机器学习框架

概述 FLAML&#xff08;Fast and Lightweight AutoML&#xff09;是微软开发的一个高效的自动机器学习&#xff08;AutoML&#xff09;框架。它专注于在有限的计算资源和时间约束下&#xff0c;自动化机器学习管道的构建过程&#xff0c;包括特征工程、模型选择、超参数调优等…

Github 以及 Docker的 wsl --list --online无法访问问题

修改电脑DNS 腾讯 DNS IP&#xff1a;119.29.29.29 备用&#xff1a;182.254.116.116 阿里DNS IP&#xff1a;223.5.5.5 223.6.6.6 百度DNS IP:180.76.76.76 谷歌DNS IP:8.8.8.8

Go 语言中的变量和常量

这篇文章已经放到腾讯智能工作台的知识库啦&#xff0c;链接在这里&#xff1a;ima.copilot-Go 入门到入土。要是你有啥不懂的地方&#xff0c;就去知识库找 AI 聊一聊吧。 1、变量的声明与使用 我们来探讨编程语言中最核心的概念之一&#xff1a;变量。 1、静态语言中的变量…

破局传统订货!云徙渠道订货系统赋能企业数字化渠道升级

在数字化浪潮的推动下&#xff0c;传统经销商订货模式面临着诸多挑战&#xff0c;如信息孤岛、系统崩溃、移动化不足等问题。云徙渠道订货系统凭借其创新的数字化架构和强大的功能模块&#xff0c;正在成为企业实现渠道数字化转型的重要工具。 系统功能与创新 云徙渠道订货系统…

SQL关键字三分钟入门:UNION 与 UNION ALL —— 数据合并全攻略

在处理数据时&#xff0c;有时我们需要将来自不同表或同一表的不同查询结果合并在一起。例如&#xff1a; 合并两个部门的员工名单&#xff1b;将多个地区的销售数据汇总&#xff1b;显示某段时间内所有新增和修改的记录。 这时候&#xff0c;我们就需要用到 SQL 中非常强大的…

SNMPv3 的安全命名空间详解

1. 安全命名空间的本质 安全命名空间是 SNMPv3 的核心安全机制&#xff0c;通过 上下文&#xff08;Context&#xff09; 实现&#xff1a; #mermaid-svg-6cV9146nTFF1zCMJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#merma…

【嵌入式硬件实例】-555定时器实现烟雾和易燃气体泄露检测

555定时器实现烟雾和易燃气体泄露检测 文章目录 555定时器实现烟雾和易燃气体泄露检测1、555定时器介绍2、MQ-2 气体/烟雾传感器模块介绍3、硬件准备与接线在本文中,我们将使用555定时器和MQ-2气体传感器构建一个气体泄漏检测和报警系统。它在煤气泄漏期间用作家庭安全警报器。…

【机器人】DualMap 具身导航 | 动态场景 开放词汇语义建图 导航系统

DualMap 是一个在线的开放词汇语义映射系统&#xff0c;使得机器人能够通过自然语言查询在动态变化的环境中理解和导航 双地图导航&#xff0c;结合全局抽象地图进行高层次候选选择&#xff0c;以及局部具体地图进行精确目标定位&#xff0c;有效管理和更新环境中的动态变化。…

【Fifty Project - D37】

fifty project算是失败了一半了 成功的那一半在于一定程度上拯救了我的作息和健康&#xff0c;两个月前入职体检的肝有点不健康&#xff0c;昨天复查发现全都回到了健康范围&#xff01;尿酸也在正常范围&#xff01;就是体重还是没减下来hhh 失败的一半在于自己很差劲的规划能…