当前位置: 首页 > news >正文

Java集合中的 LinkedList

本文主要是在单向不带头链表的基础上,探讨并实现的双向不带头链表 LinkedList。

一、认识 LinkedList

说明:

1、在集合框架中,LinkedList 也实现了List接口;

2、LinkedList 的底层使用了双向链表;

3、LinkedList 没有实现 RandomAccess 接口,因此 LinkedList 不支持随机访问;

4、LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)

5、LinkedList比较适合任意位置插入的场景。

        在具体实现 LinkedList 的方法前,我们需要注意,单向链表不能回退找前一个节点,但是双向链表可以通过 prev 引用找到前一个节点,因此定义的临时变量比单向链表少。

二、LinkedList 的模拟实现

        与单向链表的功能一致。其中 display()、size()、contains() 方法一模一样,而其他方法因为不用考虑前一个节点怎么获得的问题,因此需要重写画图思考如何实现。

重点是删除节点的方法:

public class MyLinkedList{static class ListNode{public int val;public ListNode prev;public ListNode next;public ListNode(int val){this.val = val;}}public ListNode head;public ListNode last;   // 标志最后一个节点public void display(){ListNode cur = head;while(cur != null){System.out.print(cur.val + " ");cur = cur.next;}System.out.println();}public int size(){int count = 0;ListNode cur = head;while(cur != null){count++;cur = cur.next;}return count;}public boolean contains(int key){ListNode cur = head;while(cur != null){if(cur.val == key){return true;}cur = cur.next;}return false;}public void addFist(int data){ListNode newNode = new ListNode(data);if(head == null){head = last = newNode;return;}head.prev = newNode;newNode.next = head;head = newNode;}public void addLast(int data){ListNode newNode = new ListNode(data);if(head == null){head = last = newNode;return;}last.next = newNode;newNode.prev = last;last = newNode;}public void addIndex(int index, int data) throws IllegalIndexException{  // 自己编写的异常处理int len = this.size();  // 两次使用size()时用变量进行存储可提高效率if(index < 0 || index > len){throw new IllegalIndexException("指定位置不合法!!!");}if(index == 0){addFist(data);return;}if(index == len){addLast(data);return;}ListNode newNode = new ListNode(data);ListNode cur = findIndex(index);newNode.next = cur;cur.prev.next = newNode;newNode.prev = cur.prev;cur.prev = newNode;}private ListNode findIndex(int index) {ListNode cur = head;while (index != 0) {cur = cur.next;index--;}return cur;}public void remove(int key) {ListNode cur = head;while (cur != null){if (cur.val == key){if (cur == head){  // 开头head = head.next;if (head != null){  // 考虑了只有一个节点就不进来head.prev = null;}}else{cur.prev.next = cur.next;  // 中间和结尾的删除if (cur.next == null){     // 尾节点的删除last = last.prev;}else{cur.next.prev = cur.prev;  // 中间节点的删除}}return;   // 删除完毕,循环结束}cur = cur.next;  // cur.val != key 就前进}}public void removeAllKey(int key) {ListNode cur = head;while (cur != null){if (cur.val == key){if (cur == head){head = head.next;if (head != null){head.prev = null;}}else{cur.prev.next = cur.next;if (cur.next == null){last = last.prev;}else{cur.next.prev = cur.prev;}}//return;   // 比remove少了该语句,}cur = cur.next;  // cur.val != key 就前进}}public void clear() {ListNode cur = head;while (cur != null){ListNode perNode = cur.next;cur.prev = null;cur.next = null;cur = perNode;}head = last = null;}
}

三、LinkedList 的方法

与 ArrayList 一致。此处不再赘述。

方法解释
size()获取有效元素个数
boolean add(E e)尾插 e
void add(int index, E element)将 e 插入到 index 位置
boolean addAll(Collection<? extends E> c)尾插 c 中的元素
E remove(int index)删除 index 位置元素,该元素之后的元素统一往前搬移一个位
boolean remove(Object o)删除遇到的第一个 o
E get(int index)获取下标 index 位置元素
E set(int index, E element)将下标 index 位置元素设置为 element
void clear()清空
boolean contains(Object o)判断 o 是否在线性表中
int indexOf(Object o)返回第一个 o 所在下标
int lastIndexOf(Object o)返回最后一个 o 的下标
List subList(int fromIndex, int toIndex)截取部分 list

四、ArrayList 顺序表 与 LinkedList 链表的不同

不同点ArrayListLinkedList
存储方式物理上一定连续,即逻辑上相邻的元素在内存中也相邻。逻辑相邻的元素物理位置不相邻
随机访问通过下标直接访问元素,时间复杂度为O(1)不支持随机访问,查询节点数据的时间复杂度为O(N)
插入/删除头部或中间插入/删除元素时,需移动其他元素,最坏情况下时间复杂度为O(N)只需要修改指针指向,操作时间复杂度为O(1)
扩容机制需预分配连续空间,扩容成本高且可能造成空间浪费按需分配空间,动态管理内存,无扩容成本
适用场景适用于数据量稳定、频繁随机访问的场景(如缓存数据)适用于频繁插入/删除操作且数据量不确定的场景(如动态列表)
空间利用率一次性申请大量空间,可能造成空间浪费按需分配,空间利用率更高
http://www.dtcms.com/a/323918.html

相关文章:

  • 通过sealos工具在ubuntu 24.02上安装k8s集群
  • JavaScript性能优化30招实战指南
  • JUC学习笔记-----ReentrantLock
  • 怎么用java实现视频逐帧截图并保存
  • ELK分布式日志采集系统
  • 二、Linux 设置文件系统扩展属性
  • 242. 有效的字母异位词
  • 【Html网页模板】炫酷科技风公司首页
  • 元数据管理与数据治理平台:Apache Atlas 通知和业务元数据 Notifications And Business Metadata
  • Java学习第一百二十二部分——HTTPS
  • Apache Pulsar性能与可用性优化实践指南
  • JavaWeb(苍穹外卖)--学习笔记17(Apache Echarts)
  • JavaWeb(苍穹外卖)--学习笔记18(Apache POI)
  • 元数据管理与数据治理平台:Apache Atlas 分类传播 Classification Propagation
  • Qt 框架全面解析:从基础到应用
  • Android 四大布局:使用方式与性能优化原理
  • ES 调优帖:Gateway 批量写入性能优化实践
  • Redis基本原理,性能优化和参数调优简述
  • #C语言——刷题攻略:牛客编程入门训练(八):分支控制(二)
  • es-drager-blog
  • 编程与数学 03-003 计算机操作系统 15_设备管理(三):缓冲技术与I/O性能优化
  • opencv颜色识别项目:识别水果
  • 复现论文《多无人机协同任务分配算法设计与实现》
  • js 实现 ajax 并发请求
  • selenium自动化测试速成
  • 腾讯云EdgeOne KV存储在游戏资源发布中的技术实践与架构解析
  • 嵌入式开发学习(第三阶段第四天 Linux系统开发)
  • 每日任务day0810:小小勇者成长记之武器精炼
  • Docker部署到实战
  • Java 大视界 -- Java 大数据机器学习模型在电商商品销量预测与库存精准管理中的应用(391)