数据结构入门到入土——链表(完)LinkedList

目录

一,双向链表

1.单向链表的缺点

2.什么是双向链表?

3.自主实现双向链表

接口实现:

二,LinkedList

1.LinkedList的使用

1.1 什么是LinkedList?

1.2 LinkedList的使用

1.LinkedList的构造

2.LinkedList的其它常用方法介绍

3.LinkedList的遍历

三,ArrayList与LinkedList的区别


一,双向链表

1.单向链表的缺点

再了解单向链表的实现以及使用过后,我们发现单项链表存在存在缺点:

1.如下图,当cur访问下一个节点时无法再访问到上一个节点

2.尾插法的时间复杂度为O(N)

为应对该类问题,于是就有了双向链表

2.什么是双向链表?

定义:双向链表由一系列的节点组成,每个节点包含两个指针,分别指向前一个节点和后一个节点。与单向链表不同,双向链表可以从任意节点开始,向前或向后遍历链表。

如下图所示:

这是一个无头双向链表,从中我们不难看出它与无头单向链表的区别:

1.不仅有头节点通过next进行顺序访问,还有尾节点通过prev进行逆序访问

2.额外有一个prev域访问上一个已访问过的节点

3.自主实现双向链表

接口实现:

接口部分:

public interface IList {//头插法public void addFirst(int data);//尾插法public void addLast(int data);//任意位置插入,第一个数据节点为0号下标public void addIndex(int index, int data);//查找是否包含关键字key是否在单链表当中public boolean contains(int key);//删除第一次出现关键字为key的节点public void remove(int key);//删除所有值为key的节点public void removeAllKey(int key);//得到单链表的长度public int size();//打印单链表public void display();//清空单链表public void clear();}

接口重写部分:

public class MyList implements IList{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;//尾节点//头插法@Overridepublic void addFirst(int data) {ListNode node = new ListNode(data);if (this.head == null) {this.head = node;this.last = node;} else {node.next = this.head;this.head.prev = node;this.head = node;}}//尾插法@Overridepublic void addLast(int data) {ListNode node = new ListNode(data);if (this.head == null) {this.head = node;this.last = node;} else {this.last.next = node;node.prev = this.last;this.last = node;}}//任意位置插入,第一个数据节点为0号下标@Overridepublic void addIndex(int index, int data) {ListNode node = new ListNode(data);ListNode cur = this.head;if (index >= 0 && index <= size()) {if (index == 0) {addFirst(data);return;}if (index == size()) {addLast(data);return;}int count = 1;while (cur != null) {ListNode curNext = cur.next;if (count == index) {node.next = curNext;curNext.prev = node;cur.next = node;node.prev = cur;}count++;cur = cur.next;}} else {throw new IndexException("添加下标异常!");}}//查找是否包含关键字key是否在单链表当中@Overridepublic boolean contains(int key) {ListNode cur = this.head;while (cur != null) {if (cur.val == key) {return true;}cur = cur.next;}return false;}//删除第一次出现关键字为key的节点@Overridepublic void remove(int key) {ListNode cur = this.head;while (cur != null) {ListNode curNext = cur.next;if (cur.val == key) {//删头节点if (cur.prev == null) {//this.head.val = null;this.head = head.next;head.prev = null;return;}//删尾节点if (cur.next == null) {//this.last.val == null;this.last = last.prev;last.next = null;return;}curNext.prev = cur.prev;cur.prev.next = curNext;return;}cur = cur.next;}}@Overridepublic void removeAllKey(int key) {ListNode cur = this.head;while (cur != null) {ListNode curNext = cur.next;if (cur.val == key) {//删头节点if (cur.prev == null) {//this.head.val = null;this.head = head.next;head.prev = null;} else if (cur.next == null) {//this.last.val == null;this.last = last.prev;last.next = null;} else {curNext.prev = cur.prev;cur.prev.next = curNext;}}cur = cur.next;}}//得到单链表的长度@Overridepublic int size() {ListNode cur = this.head;int count = 0;while (cur != null) {count++;cur = cur.next;}return count;}//打印单链表@Overridepublic void display() {ListNode cur = this.head;if (head == null) {System.out.println("[" + "]");} else {System.out.print("[");while (cur != null) {if (cur == last) {System.out.print(cur.val);} else {System.out.print(cur.val + " ");}cur = cur.next;}System.out.println("]");}}//清空单链表@Overridepublic void clear() {ListNode cur = this.head;while (cur.next != null) {ListNode curNext = cur.next;//cur.val =null;cur.prev = null;cur.next = null;}this.head = null;this.last = null;}
}

二,LinkedList

LinkedList是一个双向链表,以上双向链表便是模拟LinkedList

1.LinkedList的使用

1.1 什么是LinkedList?

LinkedList的官方文档

LinkedList的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。
在集合框架中,LinkedList也实现了List接口
【说明】
1. LinkedList实现了List接口
2. LinkedList的底层使用了双向链表
3. LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
4. LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
5. LinkedList比较适合任意位置插入的场景

1.2 LinkedList的使用

1.LinkedList的构造
方法
解释
LikedList()
无参构造
public LinkedList(Collection<? extends E> c)
使用其他集合容器中元素构造 List

public static void main(String[] args) {

// 构造一个空的LinkedList

List<Integer> list1 = new LinkedList<>();

List<String> list2 = new java.util.ArrayList<>();

list2.add("JavaSE");

list2.add("JavaWeb");

list2.add("JavaEE");

// 使用ArrayList构造LinkedList

List<String> list3 = new LinkedList<>(list2);

}

2.LinkedList的其它常用方法介绍
方法
解释
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<E> subList (int fromIndex, int toIndex)
截取部分 list

public static void main(String[] args) {

LinkedList<Integer> list = new LinkedList<>();

list.add(1); // add(elem): 表示尾插

list.add(2);

list.add(3);

list.add(4);

list.add(5);

list.add(6);

list.add(7);

System.out.println(list.size());

System.out.println(list);

// 在起始位置插入0

list.add(0, 0); // add(index, elem): index位置插入元素elem

System.out.println(list);

list.remove(); // remove(): 删除第一个元素,内部调用的是removeFirst()

list.removeFirst(); // removeFirst(): 删除第一个元素

list.removeLast(); // removeLast(): 删除最后元素

list.remove(1); // remove(index): 删除index位置的元素

System.out.println(list);

// contains(elem): 检测elem元素是否存在,如果存在返回true,否则返回false

if(!list.contains(1)){

list.add(0, 1);

}

list.add(1);

System.out.println(list);

System.out.println(list.indexOf(1)); // indexOf(elem): 从前往后找到第一个elem的位置

System.out.println(list.lastIndexOf(1)); // lastIndexOf(elem): 从后往前找第一个1的位置

int elem = list.get(0); // get(index): 获取指定位置元素

list.set(0, 100); // set(index, elem): index位置的元素设置为elem

System.out.println(list);

// subList(from, to): list[from, to)之间的元素构造一个新的LinkedList返回

List<Integer> copy = list.subList(0, 3);

System.out.println(list);

System.out.println(copy);

list.clear(); // list中元素清空

System.out.println(list.size());

}

3.LinkedList的遍历

public static void main(String[] args) {

LinkedList<Integer> list = new LinkedList<>();

list.add(1); // add(elem): 表示尾插

list.add(2);

list.add(3);

list.add(4);

list.add(5);

list.add(6);

list.add(7);

System.out.println(list.size());

// foreach遍历

for (int e:list) {

System.out.print(e + " ");

}

System.out.println();

// 使用迭代器遍历---正向遍历

ListIterator<Integer> it = list.listIterator();

while(it.hasNext()){

System.out.print(it.next()+ " ");

}

System.out.println();

// 使用反向迭代器---反向遍历

ListIterator<Integer> rit = list.listIterator(list.size());

while (rit.hasPrevious()){

System.out.print(rit.previous() +" ");

}

System.out.println();

}

三,ArrayList与LinkedList的区别

不同点
ArrayList
LinkedList
存储空间上
物理上一定连续
逻辑上连续,但物理上不一定连续
随机访问
支持 O(1)
不支持: O(N)
头插
需要搬移元素,效率低 O(N)
只需修改引用的指向,时间复杂度为 O(1)
插入
空间不够时需要扩容
没有容量的概念
应用场景
元素高效存储 + 频繁访问
任意位置插入和删除频繁

完。

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

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

相关文章

Pruning Papers

[ICML 2020] Rigging the Lottery: Making All Tickets Winners 整个训练过程中mask是动态的&#xff0c;有drop和grow两步&#xff0c;drop是根据权重绝对值的大小丢弃&#xff0c;grow是根据剩下激活的权重中梯度绝对值生长没有先prune再finetune/retrain的两阶段过程 Laye…

工业异常检测AnomalyGPT-Demo试跑

写在前面&#xff1a;如果你有大的cpu和gpu可以使用&#xff0c;直接根据官方的安装说明就可以&#xff0c;如果没有&#xff0c;可以点进来试着看一下我个人的安装经验。 一、试跑环境 NVIDIA4090显卡24g,cpu内存33G&#xff0c;交换空间8g,操作系统ubuntu22.04(试跑过程cpu…

SEO写作:撰写在Google上排名的博客文章的13个技巧

随着排名的提高&#xff0c;您的网站可以提高其整体知名度。最终目标是通过有效的优化来推动自然流量&#xff0c;增加转化率&#xff0c;并实现业务目标。 如果你不针对搜索引擎优化你的内容&#xff0c;你的网站可能会在搜索引擎结果页面&#xff08;SERP&#xff09;上出现…

第7章-第9节-Java中的Stream流(链式调用)

1、什么是Stream流 Lambda表达式&#xff0c;基于Lambda所带来的函数式编程&#xff0c;又引入了一个全新的Stream概念&#xff0c;用于解决集合类库既有的鼻端。 2、案例 假设现在有一个需求&#xff0c; 将list集合中姓张的元素过滤到一个新的集合中&#xff1b;然后将过滤…

详解Oracle数据库的启动

Oracle数据库的启动&#xff0c;其概念可参考Overview of Instance and Database Startup。 其过程可参见下图&#xff1a; 当数据库从关闭状态进入打开数据库状态时&#xff0c;它会经历以下阶段。 阶段Mount状态描述1实例在没有挂载数据库的情况下启动实例已启动&#xff…

SpringBoot 注解超全详解

使用注解的优势&#xff1a; 采用纯java代码&#xff0c;不在需要配置繁杂的xml文件 在配置中也可享受面向对象带来的好处 类型安全对重构可以提供良好的支持 减少复杂配置文件的同时亦能享受到springIoC容器提供的功能 1 注解详解&#xff08;配备了完善的释义&#xff0…

深入了解鸿鹄工程项目管理系统源码:功能清单与项目模块的深度解析

工程项目管理软件是现代项目管理中不可或缺的工具&#xff0c;它能够帮助项目团队更高效地组织和协调工作。本文将介绍一款功能强大的工程项目管理软件&#xff0c;该软件采用先进的Vue、Uniapp、Layui等技术框架&#xff0c;涵盖了项目策划决策、规划设计、施工建设到竣工交付…

5分钟彻底搞懂什么是token

大家好啊&#xff0c;我是董董灿。 几年前在一次工作中&#xff0c;第一次接触到自然语言处理模型 BERT。 当时在评估这个模型的性能时&#xff0c;领导说这个模型的性能需要达到了 200 token 每秒&#xff0c;虽然知道这是一个性能指标&#xff0c;但是对 token 这个概念却不…

新年喝酒有讲究,怎么喝葡萄酒呢?

中国的新年有着独特又深远的意义&#xff0c;无论人在天涯海角&#xff0c;回家团圆是每个人的心愿。新年亲朋好友欢聚一堂&#xff0c;没有酒哪有气氛&#xff0c;所以喝酒是必不可少的活动项目。云仓酒庄的品牌雷盛红酒LEESON分享那么&#xff0c;新年喝啥酒&#xff0c;葡萄…

uniapp 创建组件

组件&#xff1a;用于将某个功能的 HTML、CSS、JS 封装到一个文件中&#xff0c;提高代码的复用性和可维护性。 创建组件 一、在根目录中创建 components 文件夹&#xff0c;右键点击新建组件。 二、输入组件名称、选择默认模板、点击创建组件。 三、在组件中正常编写内容即可…

什么是MOM,与MES系统的差异是什么

MOM基本概念介绍 由于绝大多数MES只关注生产执行的核心作用, 对维护管理、质量管理和库存管理的重视程度有限,有时甚至缺少这部分功能, 并且未提高到与生产运营相类似的复杂程度, 难以充分满足现代制造企业对其制造运营区域的业务管理需求, 进而直接影响对企业的运营管理效果。…

C/C++学习笔记 vcpkg使用备忘及简要说明

一、简述 vcpkg 是一个免费的 C/C 包管理器&#xff0c;用于获取和管理库。从 1500 多个开源库中进行选择&#xff0c;一步下载并构建&#xff0c;或者添加您自己的私有库以简化构建过程。由 Microsoft C 团队和开源贡献者维护。 官方教程 vcpkg 文档 | Microsoft Learnvcpkg …

数据结构与算法(十)深度优先搜索与广度优先搜索

广度优先搜索 广度优先搜索&#xff1a;从一个顶点出发&#xff08;由开始时顶点创造顺序优先决定&#xff09;&#xff0c;访问所有没有被访问过的临节点。然后在从被访问过的节点出发&#xff0c;重复之前的操作 如下为一个图 从1出发&#xff0c;先后访问2 3&#xff0c;之后…

横版长图一键切割,短图制作高效又便捷!

在数字时代&#xff0c;图片处理已经成为了我们日常工作和生活中不可或缺的一部分。为了满足大家对于高效、便捷的图片处理需求&#xff0c;我们推出了一款全新的图片处理工具——横版长图一键切割&#xff01; 首先&#xff0c;我们进入首助编辑高手主页面&#xff0c;会看到…

优化改进YOLOv8算法之AKConv(可改变核卷积),即插即用的卷积,效果秒杀DSConv

目录 1 AKConv原理 1.1 Define the initial sampling position 1.2 Alterable convolutional operation 1.3 Extended AKConv 2 YOLOv8中加入AKConv模块 2.1 AKConv.py文件配置 2.2 task.py配置 2.3 创建添加优化点模块的yolov8-AKConv.yaml 2.4 训练 1 AKConv原理 …

Docker部署 SRS rtmp/flv流媒体服务器

一、介绍 SRS&#xff08;Simple Realtime Server&#xff09;是一款开源的流媒体服务器&#xff0c;具有高性能、高可靠性、高灵活性的特点&#xff0c;能够支持直播、点播、转码等多种流媒体应用场景。SRS 不仅提供了流媒体服务器&#xff0c;还提供了适用于多种平台的客户端…

Balking模式-实例

Balking模式 所谓Balk就是停止并返回的意思。 如果守护条件不成立&#xff0c;则立即中断处理。 因为Guarded Suspension模式是一直等待至可以运行。 当写入的内容与上次写入的内容完全相同时&#xff0c; 再向文件写入就显得多余了&#xff0c; 所以就不再执行写入操作。 也就…

深度解析Dubbo的基本应用与高级应用:负载均衡、服务超时、集群容错、服务降级、本地存根、本地伪装、参数回调等关键技术详解

负载均衡 官网地址&#xff1a; http://dubbo.apache.org/zh/docs/v2.7/user/examples/loadbalance/ 如果在消费端和服务端都配置了负载均衡策略&#xff0c; 以消费端为准。 这其中比较难理解的就是最少活跃调用数是如何进行统计的&#xff1f; 讲道理&#xff0c; 最少活跃数…

欧拉图及其应用

什么是欧拉图 提到欧拉图就要谈到哥尼斯堡七桥问题&#xff0c;最初有这样的一个问题的&#xff1a;18世纪中叶&#xff0c;东普鲁士哥尼斯堡城有一条贯穿全城的普雷格尔河&#xff0c;河中有两个岛&#xff0c;通过七座桥彼此相连&#xff0c;如下图所示 问题是这样的&…

【Python学习】Python学习10-列表

目录 【Python学习】Python学习10-列表 前言创建语法访问列表中的值更新和删除列表元素操作列表列表截取Python列表函数&方法参考 文章所属专区 Python学习 前言 本章节主要说明Python的列表List。 创建语法 创建一个列表 通过方括号和逗号分割创建&#xff0c;列表数据…