【数据结构】链表与LinkedList

作者主页:paper jie 的博客

本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。

本文录入于《JAVA数据结构》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将javaSE基础知识一网打尽,希望可以帮到读者们哦。

其他专栏:《算法详解》《C语言》《javaSE》等

内容分享:本期将会分享数据结构中的链表知识

目录

链表

链表的概念与结构

单向链表的模拟实现

具体实现代码

MyLinkedList

 indexillgality

LinkedList

LinkedList的模拟实现

MyLinkedList

Indexexception

java中的LinkedList

LinkedList的使用

LinkedList的多种遍历

ArrayList与LinkedList的区别


链表

链表的概念与结构

链表是一种物理存储结构上非连续的存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的。大家可以把它理解为现实中的绿皮火车

这里要注意:

链式在逻辑上是连续的,但是在物理上不一定是连续的

现实中的结点一般都是从堆上申请出来的

从堆上申请的空间,是按照一定的策略来分配的,所以两次申请的空间可能连续,也可能不连续

链表中的结构是多样的,根据情况来使用,一般使用一下结构:

单向或双向

带头和不带头

循环和非循环

这些结构中,我们需要重点掌握两种:

无头单向非循环链表:结构简单,一般不会单独来存数据,实际上更多的是作为其他数据结构的子结构,如哈希桶,图的邻接表等。

无头双向链表:在我们java的集合框架中LinkedList低层实现的就是无头双向循环链表。

单向链表的模拟实现

下面是单向链表需要实现的一些基本功能:

// 1、无头单向非循环链表实现
public class SingleLinkedList {
//头插法
public void addFirst(int data){
} 
//尾插法
public void addLast(int data){
} 
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
} 
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
return false;
} 
//删除第一次出现关键字为key的节点
public void remove(int key){
}
//删除所有值为key的节点
public void removeAllKey(int key){
} 
//得到单链表的长度
public int size(){
return -1;
}
public void clear() {
}
public void display() {}
}

具体实现代码

MyLinkedList
package myLinkedList;import sun.awt.image.ImageWatched;import java.util.List;/*** Created with IntelliJ IDEA.* Description:* User: sun杰* Date: 2023-09-14* Time: 10:38*/
public class MyLinkedList implements IList{static class LinkNode {public int value;public LinkNode next;public LinkNode(int data) {this.value = data;}}LinkNode head;public void createNode() {LinkNode linkNode1 = new LinkNode(12);LinkNode linkNode2 = new LinkNode(23);LinkNode linkNode3 = new LinkNode(34);LinkNode linkNode4 = new LinkNode(56);LinkNode linkNode5 = new LinkNode(78);linkNode1.next = linkNode2;linkNode2.next = linkNode3;linkNode3.next = linkNode4;linkNode4.next = linkNode5;this.head = linkNode1;}@Overridepublic void addFirst(int data) {//实例化一个节点LinkNode firstNode = new LinkNode(data);if(this.head == null) {this.head = firstNode;return;}//将原第一个对象的地址给新节点的next,也就是将head给新nextfirstNode.next = this.head;//将新的对象的地址给head头this.head = firstNode;}@Overridepublic void addLast(int data) {//实例化一个节点LinkNode lastNode = new LinkNode(data);//找到最后一个节点LinkNode cur = this.head;while(cur.next!= null) {cur = cur.next;}cur.next = lastNode;//将最后一个节点的next记录插入节点的地址}@Overridepublic void addIndex(int index, int data) throws indexillgality {if(index < 0 || index > size()) {throw new indexillgality("index不合法");}LinkNode linkNode = new LinkNode(data);if(this.head == null) {addFirst(data);return;}if(size() == index ) {addLast(data);return;}LinkNode cur = this.head;int count = 0;while(count != index - 1) {cur = cur.next;count++;}linkNode.next = cur.next;cur.next = linkNode;}@Overridepublic boolean contains(int key) {LinkNode cur = this.head;while(cur != null) {if(cur.value == key) {return true;}cur = cur.next;}return false;}@Overridepublic void remove(int key) {if(this.head.value == key) {this.head = this.head.next;return ;}//找前驱LinkNode cur = findprev(key);//判断返回值if(cur != null) {//删除LinkNode del = cur.next;cur.next = del.next;//cur.next = cur.next.next;}}//找删除的前驱private LinkNode findprev(int key) {LinkNode cur = head;while(cur.next != null) {if(cur.next.value == key) {return cur;}cur = cur.next;}return null;}@Overridepublic void removeAllKey(int key) {if(size() == 0) {return ;}if(head.value == key) {head = head.next;}LinkNode cur = head.next;LinkNode prev = head;while(cur != null) {if(cur.value == key) {prev.next = cur.next;}prev = cur;cur = cur.next;}}@Overridepublic int size() {LinkNode cur = head;int count = 0;while(cur != null) {count++;cur = cur.next;}return count;}@Overridepublic void display() {LinkNode x = head;while(x != null) {System.out.print(x.value + " ");x = x.next;}System.out.println();}@Overridepublic void clear() {LinkNode cur = head;while(cur != null) {LinkNode curNext = cur.next;cur.next = null;cur = curNext;}head = null;}
}
 indexillgality

这时一个自定义异常

package myLinkedList;/*** Created with IntelliJ IDEA.* Description:* User: sun杰* Date: 2023-09-14* Time: 12:55*/
public class indexillgality extends RuntimeException {public indexillgality(String message) {super(message);}
}

LinkedList

LinkedList的模拟实现

这相当于无头双向链表的实现,下面是它需要的基本功能:

// 2、无头双向链表实现
public class MyLinkedList {
//头插法
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(){}
}

MyLinkedList

package myLinkedList;import java.util.List;/*** Created with IntelliJ IDEA.* Description:* User: sun杰* Date: 2023-09-20* Time: 18:49*/
public class MyLinkedList implements IList {//单个节点public static class ListNode {private int val;private ListNode prev;private ListNode next;public ListNode(int val) {this.val = val;}}ListNode head;ListNode last;@Overridepublic void addFirst(int data) {ListNode cur = new ListNode(data);if(head == null) {cur.next = head;head = cur;last = cur;}else {cur.next = head;head.prev = cur;head = cur;}}@Overridepublic void addLast(int data) {ListNode cur = new ListNode(data);if(head == null) {head = cur;last = cur;} else {last.next = cur;cur.prev = last;last = cur;}}@Overridepublic void addIndex(int index, int data) throws Indexexception {ListNode cur = new ListNode(data);if(index < 0 || index > size()) {throw new Indexexception("下标越界");}//数组为空时if(head == null) {head = cur;last = cur;return ;}//数组只有一个节点的时候if(head.next == null || index == 0) {head.prev = cur;cur.next = head;head = cur;return;}if(index == size()) {last.next = cur;cur.prev = last;return ;}//找到对应下标的节点ListNode x = head;while(index != 0) {x = x.next;index--;}//头插法cur.next = x;cur.prev = x.prev;x.prev.next = cur;x.prev = cur;}@Overridepublic boolean contains(int key) {ListNode cur = head;while(cur != null) {if(cur.val == key) {return true;}cur = cur.next;}return false;}@Overridepublic void remove(int key) {if(head == null) {return;}ListNode cur = head;while(cur != null) {if(cur.val == key) {if(cur.next == null && cur.prev == null) {head = null;last = null;return;}else if(cur.next == null){cur.prev.next = null;last = cur.prev;return;}else if(cur.prev == null) {head = cur.next;cur.next.prev = null;return ;}else {ListNode frone = cur.prev;ListNode curnext = cur.next;frone.next = curnext;curnext.prev = frone;return ;}}cur = cur.next;}}@Overridepublic void removeAllKey(int key) {if(head == null) {return;}ListNode cur = head;while(cur != null) {if(cur.val == key) {if(cur.next == null && cur.prev == null) {head = null;last = null;} else if(cur.next == null){cur.prev.next = null;last = cur.prev;}else if(cur.prev == null) {head = cur.next;cur.next.prev = null;}else {ListNode frone = cur.prev;ListNode curnext = cur.next;frone.next = curnext;curnext.prev = frone;}}cur = cur.next;}}@Overridepublic int size() {int count = 0;ListNode cur = head;while(cur != null) {count++;cur = cur.next;}return count;}@Overridepublic void display() {ListNode cur = head;while(cur != null) {System.out.print(cur.val + " ");cur = cur.next;}System.out.println();}@Overridepublic void clear() {if(head == null) {return;}ListNode cur = head.next;while(cur != null) {head = null;head = cur;cur = cur.next;}head = null;}
}

Indexexception

这也是一个自定义异常

package myLinkedList;/*** Created with IntelliJ IDEA.* Description:* User: sun杰* Date: 2023-09-21* Time: 9:47*/
public class Indexexception extends RuntimeException{public Indexexception(String message) {super(message);}
}

java中的LinkedList

LinkedList的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来。因为这样,在任意位置插入和删除元素时,是不需要搬移元素,效率比较高。 

在集合框架中,LinkedList也实现了List接口:

注意:

LinkedList实现了List接口

LinkedList的底层使用的是双向链表

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

LinkedList的随机位置插入和删除元素时效率较高,复杂度为O(1)

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

LinkedList的使用

LinkedList的构造:

一般来说有两种方法:

无参构造:

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

使用其他集合容器中的元素构造List:

public LinkedList(Collection<? extends E> c)

栗子:

public static void main(String[] args) {
// 构造一个空的LinkedListList<Integer> list1 = new LinkedList<>();List<String> list2 = new java.util.ArrayList<>();list2.add("JavaSE");list2.add("JavaWeb");list2.add("JavaEE");
// 使用ArrayList构造LinkedListList<String> list3 = new LinkedList<>(list2);}

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());
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());
}

LinkedList的多种遍历

foreach:

public static void main(String[] args) {List<Integer> list = new LinkedList<>();list.add(1);list.add(3);list.add(5);list.add(2);list.remove(1);for (int x:list) {System.out.print(x + " ");}}

使用迭代器遍历:

ListIterator<Integer> it = list.listIterator();while(it.hasNext()) {System.out.println(it.next() + " ");}}

ArrayList与LinkedList的区别


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

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

相关文章

计算机网络学习易错点

目录 概述 1.internet和Internet的区别 2.面向连接和无连接 3.不同的T 4.传输速率和传播速率 5.传播时延和传输时延&#xff08;发送时延&#xff09; 6.语法&#xff0c;语义和同步 一.物理层 1.传输媒体与物理层 2.同步通信和异步通信 3.位同步&#xff08;比特同…

windows WSL配置cuda,pytorch和jupyter notebook

机器配置 GPU: NVIDIA Quadro K2000 与 NVIDIA 驱动程序捆绑的CUDA版本 但按照维基百科的描述&#xff0c;我的GPU对应的compute capability3.0&#xff0c;允许安装的CUDA最高只支持10.2&#xff0c;如下所示。 为什么本地会显示11.4呢&#xff1f;对此&#xff0c;GPT是这…

数学建模Matlab之优化类方法

本文还是来源于http://t.csdnimg.cn/P5zOD&#xff0c;但肯定不可能只有这些内容&#xff0c;否则那位作者应该会打我……&#xff0c;在这里&#xff0c;只是讲解优化类问题比较常用的方法&#xff0c;以TSP问题为例&#xff0c;适合入门。 模拟退火 模拟退火是一种概率算法&a…

基于Cplex的人员排班问题建模求解(JavaAPI)

使用Java调用Cplex实现了阿里mindopt求解器的案例&#xff08;https://opt.aliyun.com/platform/case&#xff09;人员排班问题。 这里写目录标题 人员排班问题问题描述数学建模编程求解&#xff08;CplexJavaAPI&#xff09;求解结果 人员排班问题 随着现在产业的发展&#…

WPF 02

Grid容器 分行和分列 <Grid><Grid.RowDefinitions><!--2*&#xff1a;此行是下面一行的两倍--><RowDefinition Height"2*"/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/>…

【AI视野·今日Robot 机器人论文速览 第四十四期】Fri, 29 Sep 2023

AI视野今日CS.Robotics 机器人学论文速览 Fri, 29 Sep 2023 Totally 38 papers &#x1f449;上期速览✈更多精彩请移步主页 Interesting: &#x1f4da;NCF,基于Neural Contact Fields神经接触场的方法实现有效的外部接触估计和插入操作。 (from FAIR ) 操作插入处理结果&am…

ESP8266使用记录(四)

放上最终效果 ESP8266&Unity游戏 整合放进了坏玩具车遥控器里 最终只使用了mpu6050的yaw数据&#xff0c;因为roll值漂移…… 使用了https://github.com/ElectronicCats/mpu6050 整个流程 ESP8266取MPU6050数据&#xff0c;处理后通过udp发送给Unity显示出来 MPU6050_Z…

TensorFlow学习1:使用官方模型进行图片分类

前言 人工智能以后会越来越发达&#xff0c;趁着现在简单学习一下。机器学习框架有很多&#xff0c;这里觉得学习谷歌的 TensorFlow&#xff0c;谷歌的技术还是很有保证的&#xff0c;另外TensorFlow 的中文文档真的很友好。 文档&#xff1a; https://tensorflow.google.cn/…

ORACLE Redo Log Buffer 重做日志缓冲区机制的设计

最近和朋友包括一些国产数据库的研发人员交流&#xff0c;很多程序员认为 Oracle 已经过时&#xff0c;开源数据库或者他们研发的国产数据库才代表数据库发展的未来。甚至在很多交流会议上拿出自家产品的某一个功能点和 Oracle 对比就觉得已经遥遥领先。 实际上数据库系统的发展…

JVM机制理解与调优方案

作者&#xff1a;逍遥Sean 简介&#xff1a;一个主修Java的Web网站\游戏服务器后端开发者 主页&#xff1a;https://blog.csdn.net/Ureliable 觉得博主文章不错的话&#xff0c;可以三连支持一下~ 如有需要我的支持&#xff0c;请私信或评论留言&#xff01; 前言 很多Java开发…

电脑WIFI突然消失

文章目录 1. 现象2. 解决办法1&#xff1a;重新启用无线网卡设置3. 解决办法2&#xff1a;更新无线网卡驱动4. 解决办法3&#xff1a;释放静电5. 解决办法4&#xff1a;拆机并重新插拔无线网卡 1. 现象 如下图&#xff1a;电脑在使用过程中WIFI消失 设备管理器中的无线网卡驱…

【深度学习实验】卷积神经网络(六):自定义卷积神经网络模型(VGG)实现图片多分类任务

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 构建数据集&#xff08;CIFAR10Dataset&#xff09; a. read_csv_labels&#xff08;&#xff09; b. CIFAR10Dataset 2. 构建模型&#xff08;FeedForward&…

解决内网拉取企微会话存档代理问题的一种办法

问题&#xff1a;客户的服务都是内网的&#xff0c;不能直接访问外网&#xff1b;访问外网的话需要走kong网关才能出去。 会话存档官网说可以使用socket5、http方式拉取会话存档&#xff1b;我这边尝试了直接使用kong网关的ip和端口配置进去&#xff0c;是访问不了的 我后面就…

<C++> 哈希表模拟实现STL_unordered_set/map

哈希表模板参数的控制 首先需要明确的是&#xff0c;unordered_set是K模型的容器&#xff0c;而unordered_map是KV模型的容器。 要想只用一份哈希表代码同时封装出K模型和KV模型的容器&#xff0c;我们必定要对哈希表的模板参数进行控制。 为了与原哈希表的模板参数进行区分…

开源layui前端框架 收款码生成系统源码 多合一收款码生成源码 带50多套UI模板

Layui前端的多合一收款码在线生成系统源码_附多套前端UI模板。 卡特三合一收款码生成系统源码&#xff0c;和收款啦采用一样的原理。 内部多达50多套模板&#xff0c;前端跟付款界面都特别好看。 识别收款码之后会自动加密&#xff0c;非常安全。 一样没有后台&#xff0c;一样…

机器人过程自动化(RPA)入门 9. 管理和维护代码

仅仅创建一个自动化项目是不够的。无论是决定使用哪种布局,还是正确命名步骤,以正确的方式组织项目都很重要。项目也可以在新的项目中重用,这对用户来说非常方便。本章解释了我们可以重用项目的方法。我们还将学习配置技术并看到一个示例。最后,我们将学习如何集成TFS服务器…

XSS详解

XSS一些学习记录 XXS短标签、属性、事件、方法短标签属性事件函数弹窗函数一些对于绕过有用的函数一些函数使用payload收集 浏览器编码问题XML实体编码URL编码JS编码混合编码 一些绕过方法利用constructor原型污染链构造弹框空格绕过圆括号过滤绕过其他的一些绕过 参考 XXS短标…

中国1km土壤特征数据集(2010年)

简介&#xff1a; 中国1km土壤特征数据集&#xff08;2010&#xff09;是基于第二次全国土壤调查的中国1:1000000比例尺土壤图和8595个土壤剖面图&#xff0c;以及美国农业部&#xff08;USDA&#xff09;中国区域土地和气候模拟标准&#xff0c;开发了一个多层土壤粒度分布数…

Apache shiro RegExPatternMatcher 权限绕过漏洞 (CVE-2022-32532)

漏洞描述 2022年6月29日&#xff0c;Apache 官方披露 Apache Shiro &#xff08;CVE-2022-32532&#xff09;权限绕过漏洞。 当Apache Shiro中使用RegexRequestMatcher进行权限配置&#xff0c;且正则表达式中携带"."时&#xff0c;未经授权的远程攻击者可通过构造恶…

C#,数值计算——Ranlim32的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// High-quality random generator using only 32-bit arithmetic.Same conventions /// as Ran.Period is 3.11E37 . Recommended only when 64-bit arithmetic is not /// a…