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

数据结构——LinkedList和链表 - 实践

目录

一:ArrayList的缺陷

二:链表

2.1 :链表的概念及结构

2.2:链表的实现

三:LinkedList模拟实现

四:总结


一:ArrayList的缺陷

由于其底层是⼀段连续空间,当在ArrayList任意位置插⼊或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率⽐较低,因此ArrayList不适合做任意位置插⼊和删除⽐较多的场景。因此:java集合中⼜引⼊了LinkedList,即链表结构。

二:链表

2.1 :链表的概念及结构

链表是⼀种物理存储结构上⾮连续存储结构,数据元素的逻辑顺序是通过链表中的引⽤链接次序实现的 。
白话一点:
链表不要求连续的内存空间(离散的结构)
元素和元素之间,内存是不连续的,并且这些元素的空间是没啥规律的(顺序上没有要求,内存上也没有要求)
如何知道链表中包含哪些元素、如何遍历链表中所以元素?
  此处就把每个节点上面都引入一个引用变量,称为next
   使用直观引用保存下一个元素对应的内存空间。

就是在a中存放一个next如何存放b的地址,以此类推,到d中就存放一个null,后面没有元素了。

  链表的特点:
  1.链表的元素在离散的内存空间上
  2.每个元素中记录下一个元素地址(引用)
  需要知道第一个元素是谁,后续整个链表就能拿到了

实际中链表的结构⾮常多样,以下情况组合起来就有8种链表结构:

1:单向或者双向

单链表只能指知道下一个,不知道上一个
双向链表,每个节点包含两个引用,prev、next(前一个元素地址、后一个元素地址)功能多了,但是消耗的空间更多了

 2.带头或者不带头(是否带有“傀儡节点”)

头节点:应该是链表第一个节点
  傀儡节点:这个节点不存储数据,而是占位置,来简化后续代码

  其实带头也有傀儡节点,只是不显示,如图带头,其实head的next指向傀儡节点,但是傀儡节点不存储数据,那么head的next就指向d1

  3.循环或者⾮循环

重点关注:
⽆头单向⾮循环链表:结构简单,⼀般不会单独⽤来存数据。实际中更多是作为其他数据结构的⼦结构,如哈希桶、图的邻接表等等。另外这种结构在笔试⾯试中出现很多。
⽆头双向链表:在Java的集合框架库中LinkedList底层实现就是⽆头双向循环链表

在java标准库中,LinkedList就是现成的实现,都是实现List的接口。

2.2:链表的实现

package linkedlist;
import java.util.LinkedList;
public class Test1 {public static void main(String[] args) {LinkedList list = new LinkedList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(0,5);list.addFirst(6);System.out.println(list);//[6, 5, 1, 2, 3, 4]list.remove(2);// 删除索引为2的元素 1        System.out.println(list);//[6, 5, 2, 3, 4]list.remove(Integer.valueOf(2));//删除值为2的元素 2        System.out.println(list);//[6, 5, 3, 4]//头删list.removeFirst();System.out.println(list);//[5, 3, 4]//尾删list.removeLast();System.out.println(list);//[5, 3]list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);//通过get方法获取元素System.out.println(list.get(2));//3//通过set方法修改元素list.set(2, 10);System.out.println(list);//[1, 2, 10, 4, 1, 2, 3, 4, 5]//通过contians方法判断是否包含元素list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);System.out.println(list.contains(3));//trueSystem.out.println(list.contains(6));//false}
}

三:LinkedList模拟实现

以下代码模拟实现都有注释,如果有不理解的可以评论O~~~

package linkedlist;
//表示链表的节点
class Node {// 节点保存值public String value;// 指向下一个节点public Node next;public Node(String value) {this.value = value;this.next = null;}
}
public class MyLinkedList {//把链表的头节点表示出来,此时整个链表就能获取了//此时不包含傀儡节点,head==null的时候表示空链表private Node head=null;//不像顺序表使用size表示区间的长度,链表使用length表示链表的长度//但也可以使用size表示个数。//插入元素//1:尾插(先找到尾巴,再插入)public void addlast(String value){//如果链表为空if(head==null){//新建一个节点Node newNode=new Node(value);//把新节点放到头部head=newNode;return;        }//先找道尾巴,把新的节点加道尾巴后面//先创建一个头节点Node tail=head;for(;tail.next!=null;tail=tail.next){if(tail.next==null){break;}}//找到尾巴//新建一个节点Node newNode=new Node(value);tail.next=newNode;newNode.next=null;}//2:头插(public void addfirst(String value) {//新建一个节点Node newNode = new Node(value);//把新节点放到头部//1:就要将newNode的next指向head指向的节点newNode.next = head;//2:然后我们的head在指向(新节点)newNodehead = newNode;}//3:指定位置插入//在链表中没有下标的概念//链表需要遍历,找位置。//但是java标准库,LinkedList同样引入下标这个概念,使用List统一作为ArrayList和LinkedList的接口public void add(int index,String value) {//先判断index是否合法if (index < 0 || index > size()) {//index==size等于尾插,没必要判断throw new IndexOutOfBoundsException("Index is out of bounds");}//针对头插出现的情况if(index==0){addfirst(value);return;        }//根据当前value值,创建新的节点Node cur = new Node(value);//找到index位置的前一个节点//由于当前链表是单向链表,每个节点稚只能找到next节点//需要修改前一个节点next的值,让它指向当前节点//插入新节点,需要找到index-1位置的节点Node prev = head;for(int i=0;i= size()){throw new IndexOutOfBoundsException("Index is out of bounds");}//特殊处理index为0的情况if(index==0){head=head.next;return;        }//找到被删除元素前一个节点位置Node prev=head;for(int i=0;i

关于clear:
一旦head==null,此时1就没有无人指向
1这个节点,就会被GC给释放掉了
1被释放之后,2就没有人指向了,2也会被GC释放,后面也差不多,依此类推。

四:总结

本篇博客讲述了链表的概念以及使用方法,最后模拟实现了链表。

如果有不明白的可以评论哦。

http://www.zskr.cn/news/31265.html

相关文章:

  • 10 25
  • 2025 年青岛点焊机厂家最新推荐榜,聚焦技术实力与市场口碑深度解析螺母/自动/螺栓/储能/汽车零部件点焊机厂家推荐
  • 日记14
  • 三年级小学生日记范文
  • easy-query暴打efcore(包括其他所有orm),隐式Group看我如何在子查询做到极致的性能天花板
  • 完整教程:深入理解-自然拼读(英语)
  • 能在0.02秒内找到最优解的华容道程序
  • Sparkle签名检查绕过漏洞分析
  • dataGridView 控件表格颜色交替设置
  • 2025年10月洗地机产品推荐榜:价格与性能全面对比
  • 读AI赋能11自由认知
  • SAM2 图像分割(3)鼠标选择多框 摄像头实时分割显示 - MKT
  • Semantic-SSAM 是“一切多细都行,还能给标签”​​ - MKT
  • P1679 神奇的四次方数
  • 20232419 2025-2026-1 《网络与系统攻防技术》实验三实验报告
  • 详细介绍:分布式任务事务框架设计与实现方案
  • 事件日志查看Windows安装软件情况
  • 凭借Ubuntu和i.MX 6ULL开发板构建网络共享
  • 【CI130x 离在线】FreeRTOS的流缓冲(StreamBuffer)
  • 循环
  • RT-Thread Nano源码浅析
  • 关于SQLite - 世界上装机量最多的数据库
  • 第六章习题
  • 概率论测试
  • 2025/10/26
  • 大学生为什么要认真听课
  • 记录一下
  • 实用指南:基于Springboot的DDD实战(不依赖框架)
  • 我是如何通过开发微信小游戏赚得人生第一桶金的
  • 以听筑基,以行践知:解锁学习新范式的思考