数据结构之LinkedList与链表(上)

找往期文章包括但不限于本期文章中不懂的知识点:

个人主页:我要学编程(ಥ_ಥ)-CSDN博客

所属专栏:数据结构(Java版)

目录

手动实现单链表的源码

手动实现双链表的源码

分析 LinkedList 的源码 

LinkedList的使用 

常用方法 

ArrayList和LinkedList的区别


单链表的学习,点我

上面这篇博文是关于链表的基础知识、链表的分类以及单链表的实现。都详细的进行了说明。

手动实现单链表的源码

下面是Java版的链表源码: 

// 无头单向非循环链表实现
public class SingleLinkedList {// 链表是有一个一个的节点组成,因此得先创建节点// 链表的节点由两部分组成:数值域与地址域// 既然有多个部分,那么就可以写在类中// 又因为节点是在单链表中(单链表中包含一个又一个的节点)// 因此节点就可以成为单链表的内部类// 静态内部类可以只通过类名来访问,方便public static class listNode {public int val; // 存放数值// 是一个引用指向下一个节点的地址public listNode next; // 指向下一个节点的地址public listNode(int val) {// 新创建的节点的next应该为null,因为next为字段。因此其默认值为null,无需修改this.val = val;}}public listNode head; // 头节点// 头插法public void addFirst(int data){listNode newNode = new listNode(data);// 先判断这个链表是否有节点if (head == null) {//那么新增的这个节点就是头节点head = newNode;}else {// 把新节点的next指向head,并且把head指向新节点newNode.next = head;head = newNode;}}// 尾插法public void addLast(int data){listNode newNode = new listNode(data);// 先判断这个链表是否为空if (head == null) {head = newNode;}else {listNode cur = head;// 找到尾节点while (cur.next != null) {cur = cur.next;}// 将尾节点的next指向新节点,就完成了尾插cur.next = newNode;}}// 任意位置插入,第一个数据节点为0号下标public boolean addIndex(int index,int data) throws AddIndexofException{// 先判断插入的位置是否合法if (index < 0 || index > size()) {throw new AddIndexofException("addIndex() index位置异常");}// 先判断这个链表是否为空,如果是空,既可以采取尾插,也可以采取头插if (head == null) {addLast(data);}else if (index == 0) {addFirst(data);}else {listNode newNode = new listNode(data);// 找到pos-1的位置listNode cur = head;while (index-1 > 0) {cur = cur.next;index--;}// 两个的顺序不能变newNode.next = cur.next;cur.next = newNode;return true;}return false;}// 查找是否包含关键字key是否在单链表当中public boolean contains(int key){// 先判断链表是否为空if (head == null) {return false;}listNode cur = head;while (cur != null) {if (cur.val == key) {return true;}cur = cur.next;}return false;}// 删除第一次出现关键字为key的节点public void remove(int key) throws SingleLinkedisEmptyException, NotFindException{// 判断链表是否为空if (head == null) {throw new SingleLinkedisEmptyException("单链表为空异常");} else if (head.next == null) {// 如果链表中只有一个元素的话,直接删除就行if (head.val == key) {head = null;return;}else {throw new NotFindException("找不到要删除的数异常");}        } else if (head.val == key) {// 头删head = head.next;return;} else {listNode cur = head;while (cur.next != null) {if (cur.next.val == key) {// 开始删除listNode del = cur.next.next;cur.next = cur.next.next;// 可能这里会有疑惑被删除的节点的next不是还指向了其后一个位置吗?// 这样会不会有问题呢?当一个对象每人引用时,就会被标记回收// 当然手动置为null,也是可以的del = null;return;}cur = cur.next;}}throw new NotFindException("找不到要删除的数异常");}// 删除所有值为key的节点public void removeAllKey(int key){boolean flag = true;// 判断链表是否为空if (head == null) {throw new SingleLinkedisEmptyException("单链表为空异常");} else if (head.next == null) {// 如果链表中只有一个元素的话,直接删除就行if (head.val == key) {head = null;return;}else {throw new NotFindException("没有找到要删除的数据!");}} else if (head.val == key) {// 如果头节点的值key,那就循环删除直至头节点的不为keywhile (head.val == key) {// 如果删除的只剩下最后一个节点了,就删除返回就行if (head.next == null) {head = head.next;return;}}flag = false;} else {listNode cur = head;while (cur.next != null) {if (cur.next.val == key) {// 开始删除listNode del = cur.next.next;cur.next = cur.next.next;// 可能这里会有疑惑被删除的节点的next不是还指向了其后一个位置吗?// 这样会不会有问题呢?当一个对象每人引用时,就会被标记回收// 当然手动置为null,也是可以的del = null;flag = false;}else {// 可能会出现连续的数字的情况// 因此删除之后,还得判断这个cur之后的元素是否为keycur = cur.next;}}}if (flag) {throw new NotFindException("找不到要删除的数异常");}}// 得到单链表的长度public int size(){// 先判断这个链表是否为空if (head == null) {return 0;}listNode cur = head;int count = 0;while (cur != null) {count++;cur = cur.next;}return count;}// 打印链表public void display(){listNode cur = head;while (cur != null) {System.out.print(cur.val+" ");cur = cur.next;}System.out.println();}// 清空链表public void clear(){// 暴力解法:把head置为null,那么就没有引用指向这个头节点了// 那么这个头节点就会被垃圾回收器给回收掉// head = null;// 上面那种方式可能会出现不安全的情况,因此采用遍历的形式listNode cur = head;while (cur != null) {// cur.val = null;listNode curNext = cur.next;cur.next = null;cur = curNext;}head = null;}
}

AddlndexofException异常: 

public class AddIndexofException extends RuntimeException{public AddIndexofException() {super();}public AddIndexofException(String msg) {super(msg);}
}

 NotFindException异常:

public class NotFindException extends RuntimeException{public NotFindException() {super();}public NotFindException(String msg) {super(msg);}
}

 SingleLinkedisEmptyException异常:

public class SingleLinkedisEmptyException extends RuntimeException{public SingleLinkedisEmptyException() {super();}public SingleLinkedisEmptyException(String msg) {super(msg);}
}

 这里来说明一下:为什么节点的引用是节点类型?

首先,我们最开始在学习引用的时候,说过引用其实就是一个变量类型,用来存放地址。而在C语言中是用指针来存放地址,按照C语言的说法,节点的地址就得用节点类型的指针来接收。那么listNode 类型的 next,就得用 listNode 来接收(引用)。就好像,在 new 应该对象时,这个对象的地址会给到一个引用变量,而这个引用变量的类型就是 new 关键字后面的。例如:Person person = new Person();  。

双链表的学习,点我

上面这篇博文是关于链表的基础知识、链表的分类以及单链表的实现。都详细的进行了说明。

手动实现双链表的源码

public class MyLinkedList implements LinkedList {//创建一个节点内部类static class ListNode {int val;ListNode prev;ListNode next;public ListNode(int val) {this.val = val;}}public ListNode head;public ListNode last;// 头插@Overridepublic void addFirst(int data) {// 创建一个新的节点ListNode newNode = new ListNode(data);// 先判断链表是否为空if (head == null) {head = newNode;last = newNode;}else {newNode.next = head;head.prev = newNode;head = newNode;}}@Overridepublic void addLast(int data) {// 创建一个新的节点ListNode newNode = new ListNode(data);// 先判断链表是否为空if (head == null) {head = newNode;last = newNode;}else {last.next = newNode;newNode.prev = last;last = newNode;}}@Overridepublic void addIndex(int data, int index) throws addIndexOfException {// 判断这个index是否合法if (index < 0 || index > size()) {// 抛异常throw new addIndexOfException("下标位置不合法异常!");}if (index == 0) {// 头插addFirst(data);} else if (index == size()) {// 尾插addLast(data);} else {// 创建一个新的节点ListNode newNode = new ListNode(data);ListNode cur = head;// 找到要插入的前一个位置while (index-1 > 0) {cur = cur.next;index--;}ListNode curNext = cur.next;cur.next = newNode;newNode.next = curNext;newNode.prev = cur;curNext.prev = newNode;}}@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) {// 链表为空,就抛异常throw new LinkedListIsEmptyException("链表为空异常!");}else if (head.next == null) {// 链表里面只有一个元素if (head.val == key) {head = null;last = null;return;}else {throw new NotFindException("找不到要删除的数异常!");}}else {// 头删if (head.val == key) {head = head.next;return;} else if (last.val == key) {// 尾删last = last.prev;last.next = null;return;}ListNode cur = head;while (cur != null) {if (cur.val == key) {// 开始删除ListNode curNext = cur.next;cur.prev.next = curNext;curNext.prev = cur.prev;return;}cur = cur.next;}throw new NotFindException("找不到要删除的数异常!");}}@Overridepublic void removeAllkey(int key) {if (head == null) {// 链表为空,就抛异常throw new LinkedListIsEmptyException("链表为空异常!");}else if (head.next == null) {// 链表里面只有一个元素if (head.val == key) {head = null;last = null;return;}else {throw new NotFindException("找不到要删除的数异常!");}}else {boolean flag = false;// 头删while (head.val == key) {flag = true;head = head.next;if (head == null) {return;}}while (last.val == key) {// 尾删flag = true;last = last.prev;last.next = null;}ListNode cur = head;while (cur != null) {if (cur.val == key) {// 开始删除flag = true;ListNode curNext = cur.next;cur.prev.next = curNext;curNext.prev = cur.prev;}cur = cur.next;}if (!flag) {throw new NotFindException("找不到要删除的数异常!");}}}@Overridepublic int size() {ListNode cur = head;int count = 0;while (cur != null) {count++;cur = cur.next;}return count;}@Overridepublic void clear() {// 暴力做法// head = last = null;// 温柔做法ListNode cur = head;while (cur != null) {// cur.val = null;cur.prev = null;ListNode curNext = cur.next;cur.next = null;cur = curNext;}head = last = null;}@Overridepublic void display() {ListNode cur = head;while (cur != null) {System.out.print(cur.val+" ");cur = cur.next;}System.out.println();}
}

 addlndexOfException异常:

public class addIndexOfException extends RuntimeException {public addIndexOfException(String msg) {super(msg);}public addIndexOfException() {super();}
}

LinkedListlsEmptyException异常:

public class LinkedListIsEmptyException extends RuntimeException {public LinkedListIsEmptyException(String msg) {super(msg);}public LinkedListIsEmptyException() {super();}
}

 NotFindException异常:

public class NotFindException extends RuntimeException {public NotFindException(String msg) {super(msg);}public NotFindException() {super();}
}

单链表和双链表在代码上,总体来说,大差不差。

分析 LinkedList 的源码 

LinkedList的底层使用了双向链表 

LinkedList的使用 

构造方法与 ArrayList 差不多,只有一个无参的和一个带参数的。带参的类型是实现了Collection接口就行。

常用方法 

方法说明
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 lastlndexOf(Object o)返回最后一个o的下标
List<E> subList(int fromlndex, int tolndex)截取部分list 

同样这里 subList 的截取不会产生新的对象。

其遍历方式和 ArrayList 是一样的。

ArrayList和LinkedList的区别

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

好啦!本期 数据结构之LinkedList与链表(上)的学习之旅就到此结束啦!我们下一期再一起学习吧!

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT关联技术

ChatGPT关联技术 一、前馈神经网络二、序列到序列模型&#xff08;Seq2Seq&#xff09;三、自注意力机制四、多头自注意力机制五、自监督学习六、Transformer模型七、语言生成技术八、多语种语言模型九、预训练语言模型十、生成式预训练模型&#xff08;GPT&#xff09;十一、近…

人民日报:高考填志愿十问十答,填报志愿时需要考虑哪些因素?

高考结束&#xff0c;志愿填报即将开始&#xff0c;填报志愿时需要考虑哪些因素&#xff1f;如何避免高分低录甚至落榜&#xff1f;高考填志愿你需要知道的事↓↓ 祝福考生考入理想大学、就读喜欢的专业。加油&#xff01; 责任编辑&#xff1a;曹继炜

【计算机网络仿真实验-实验2.6】带交换机的RIP路由协议

实验2.6 带交换机的rip路由协议 1. 实验拓扑图 2. 实验前查看是否能ping通 不能 3. 三层交换机配置 switch# configure terminal switch(config)# hostname s5750 !将交换机更名为S5750 S5750# configure terminal S5750(config)#vlan 10 S5750(config-vlan)#exit S57…

Android 工程副总裁卸任

Android 工程副总裁卸任 Android工程副总裁Dave Burke宣布&#xff0c;他将辞去领导Android工程的职位&#xff0c;将重心转向“AI/生物”项目。不过&#xff0c;他并没有离开Alphabet&#xff0c;目前仍将担任Android系统开发顾问的角色。 Burke参与了Android系统的多个关键…

偏微分方程算法之抛物型方程差分格式编程示例三(C-N格式)

目录 一、研究问题 二、C++代码 三、结果分析 一、研究问题 已知其精确解为。分别取以下三种步长: ①

随机森林算法进行预测(+调参+变量重要性)--血友病计数数据

1.读取数据 所使用的数据是血友病数据&#xff0c;如有需要&#xff0c;可在主页资源处获取&#xff0c;数据信息如下&#xff1a; import pandas as pd import numpy as np hemophilia pd.read_csv(D:/my_files/data.csv) #读取数据 2.数据预处理 在使用机器学习方法时&…

【html】学会这一套布局,让你的网页更加

很多小伙伴们在刚刚开始学习网页设计的时候不知道怎么布局今天给大家介绍一种非常实用且更加专业的一种布局。 灵感来源&#xff1a; 小米官网 布局图; 实例效果图&#xff1a; 这是一个简单的HTML模板&#xff0c;包括头部、内容区域和底部。 头部部分包括一个分为左右两部分…

有监督学习——高斯过程

1. 高斯过程 高斯过程&#xff08;Gaussian Process&#xff09;是一种假设训练数据来自无限空间且各特征都符合高斯分布&#xff08;高斯分布又称“正态分布”&#xff09;的有监督学习。 高斯过程是一种概率模型&#xff0c;在回归或分类预测都以高斯分布标准差的方式给出预…

SSM考研咨询app-计算机毕业设计源码05262

摘 要 随着互联网趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己推广出去&#xff0c;最好方式就是建立自己的互联网系统&#xff0c;并对其进行维护和管理。在现实运用中&#xff0c;应用软件的工作规则和开发步骤&#xff0c;采用Java技术建设考研咨询app。 本设计…

四川汇聚荣聚荣科技有限公司是干什么的,拼多多运营如何做?

四川汇聚荣聚荣科技有限公司是干什么的&#xff0c;拼多多运营如何做?随着电商行业的快速发展&#xff0c;越来越多的企业开始涉足这一领域。其中&#xff0c;四川汇聚荣聚荣科技有限公司便是其中的一员。那么&#xff0c;这家公司究竟是做什么的呢?简单来说&#xff0c;它是…

2078.两栋颜色不同且距离最远的房子

街上有 n 栋房子整齐地排成一列&#xff0c;每栋房子都粉刷上了漂亮的颜色。给你一个下标从 0 开始且长度为 n 的整数数组 colors &#xff0c;其中 colors[i] 表示第 i 栋房子的颜色。 返回 两栋 颜色 不同 房子之间的 最大 距离。 第 i 栋房子和第 j 栋房子之间的距离是 a…

用一个ESP32S3-Zero把有线键盘变为无线

三脚猫最近一直琢磨&#xff0c;那些喜欢买剪线键盘&#xff0c;以及自制键盘瞎折腾的人都是怎么搞的。经过不懈努力&#xff0c;终于想明白除了直接的硬件一个个pin针的高低电压判断后转给蓝牙&#xff0c;拿到现成的古董剪线键盘还有一个方式其实是在usb host转发给蓝牙类似这…

【Java】图书管理系统-控制台输出

项目原码压缩包在我主页的资源中免费领取。&#xff08;在IDEA中运行&#xff0c;启动类在src -> Main 中运行&#xff09; 图书管理系统 设计一个简单的控制台输出的图书管理系统&#xff0c;我们首先需要明确其基本功能、设计内容以及设计要求。这个系统可以包括以下几个…

C++ 50 之 继承中的对象模型

继承中的对象模型 在C编译器的内部可以理解为结构体&#xff0c;子类是由父类成员叠加子类新成员而成&#xff1a; #include <iostream> #include <string> using namespace std;class Base03{ public:int m_a; protected:int m_b; private:int m_c; // 哪怕是…

[DDR4] 总目录 学习路线

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 传送门: 总目录 目录 基础篇 1-1 DDR4 发展历史 1-2 DDR4 和 DDR3 差异与优势 1-3 DDR4 内部结构 1-4 DDR4 工作原理 协议篇 2-1 DDR4 引脚 设计篇 实践篇 进阶篇 学习路线&#xff1a; 了解DDR4的基本知识…

广东启动“粤企质量提升工作会议” 着力提升产品和服务质量

6月5日,由广东质量峰会组委会牵头,联合相关质量、信用、打假和检验检测等部门共同举办的“粤企质量提升工作会议”在广州正式启动。本次工作会议旨在贯彻落实《质量强国建设纲要》及《广东省质量强省建设纲要》精神,深入开展全民质量行动,弘扬企业家和工匠精神,营造政府重视质量…

买什么样的护眼大路灯比较好?五款专业级别的护眼灯推荐

在这个生活节奏的加快和科技的进步的时代&#xff0c;许多家长越来越关注生活质量以及身心健康问题。其中孩子的眼睛视力健康也逐渐引起了家长们的注意。 现在的孩子从早上睁开眼就开始学习&#xff0c;有时候还需要使用到电子产品辅助学习&#xff0c;晚上的写作业的情况更是…

编译安装qemu-devel @FreeBSD

缘起 使用cbsd创建riscv jail的时候提示&#xff1a; you have no qemu-user, please install qemu-devle with BSD_USER and STATIC ops (emulators/qemu-devel) 使用pkg安装之后&#xff0c;创建的riscv jail启动报错&#xff1a; Starting jail: fbriscv, parallel timeo…

iOS18新增通话录音和应用锁!附升级教程及内置壁纸

一觉睡醒&#xff0c;iOS18终于是揭开面纱了&#xff0c;而且已经有测试版给开发者使用了。 不过还是建议咱们普通用户不要轻易尝试&#xff0c;而且在升级之前一定要用iMazing做个备份&#xff0c;以免测试系统出现问题&#xff0c;丢失数据。 这次WWDC2024与之前爆料完全一样…

jupyter notebook中使用不同的anaconda环境及常用conda命令

conda命令 在jupyter notebook中使用不同的anaconda环境其他常用conda命令 在jupyter notebook中使用不同的anaconda环境 创建环境 myenvname 需替换为自己的环境名称 conda create --name myenvname python3.7激活环境 conda activate myenvname 在该环境中安装Jupyter N…