五分钟“手撕”链表

为了提高大家的学习效率,我把代码放开头,供查阅。 

目录

一、链表的实现代码

二、什么是链表

三、链表的分类

四、链表的常见操作

插入

删除 

五、Java自带的LinkedList 

 两个构造方法

 一些常用方法

六、LinkedList的遍历

七、ArrayList和LinkedList的区别  


一、链表的实现代码

//无头单向链表
package demo1;
public class MySingleLinkedList{class ListNode{public int var;public ListNode next;public int val;public ListNode(int var) {this.var = var;}}ListNode head;public void creat(){ListNode node1=new ListNode(1);ListNode node2=new ListNode(1);ListNode node3=new ListNode(1);ListNode node4=new ListNode(1);node1.next=node2;node2.next=node3;node3.next=node4;head=node1;}//头插法public void addFirst(int data) {ListNode node=new ListNode(data);node.next=head;head=node;}//尾插法public void addLast(int data) {ListNode node=new ListNode(data);if(head==null){head=node;return;}ListNode cur=head;while (cur.next!=null){cur=cur.next;}cur.next=node;}private void IndexCheck(int index)throws IndexNotLegal {if(index<0||index>size()){throw new IndexNotLegal("index位置不合法");}}//任意位置插入,第一个数据节点为0号下标public void addIndex(int index, int data){try {IndexCheck(index);}catch (IndexNotLegal e){e.printStackTrace();return;}ListNode node=new ListNode(data);ListNode cur=head;if(index==0){addFirst(data);return;}if(index==size()){addLast(data);return;}//注意这里是index-1for (int i = 0; i < index-1; i++) {cur= cur.next;}node.next=cur.next;cur.next=node;}//查找是否包含关键字key是否在单链表当中public boolean contains(int key) {ListNode cur=head;while (cur!=null){if(cur.var==key){return true;}cur=cur.next;}return false;}//删除第一次出现关键字为key的节点public void remove(int key) {if(head.var==key){head=head.next;return;}if(head==null){return;}ListNode cur=head;while (cur.next!=null){if(cur.next.var==key){cur.next=cur.next.next;return;}cur=cur.next;}}//删除所有出现的key节点public void removeAllKey(int key) {if(head==null){return;}ListNode prev=head;ListNode cur=head.next;while (cur!=null){if(cur.var==key){prev.next= cur.next;//这里不能写prev=curcur= cur.next;}else {prev=cur;cur= cur.next;}if(head.var==key){head=head.next;}}}//得到单链表的长度public int size() {ListNode cur=head;int count=0;while (cur!=null){count++;cur=cur.next;}return count;}//打印链表public void display() {ListNode cur=head;for (int i = 0; i < size(); i++) {System.out.print(cur.var+" ");cur=cur.next;}System.out.println();}//清除链表public void clear() {head=null;}
}public class IndexNotLegal extends RuntimeException {public IndexNotLegal(){}public IndexNotLegal(String s){super(s);}
}package demo2;
// 无头双向链表
public class MyLinkedList {class ListNode {public int var;ListNode prev;ListNode next;public ListNode(int var) {this.var = var;}}ListNode head;ListNode last;//头插法public void addFirst(int data) {ListNode node = new ListNode(data);if (head == null) {head = last = node;return;}node.next = head;head.prev = node;head = node;}//尾插法public void addLast(int data) {ListNode node = new ListNode(data);if (head == null) {head = last = node;return;}last.next = node;node.prev = last;last = node;}private void indexCheck(int index) throws IndexNotLegal {if (index < 0 || index > size()) {throw new IndexNotLegal("index位置不合法");}}private ListNode findIndexCur(int index) {ListNode cur = head;while (index != 0) {cur = cur.next;index--;}return cur;}//任意位置插入,第一个数据节点为0号下标public void addIndex(int index, int data) {try {indexCheck(index);} catch (IndexNotLegal e) {e.printStackTrace();}if (index == 0) {addFirst(data);return;}if (index == size()) {addLast(data);return;}ListNode node = new ListNode(data);ListNode cur = findIndexCur(index);//先把node插进去,再调整node的前一个,最后再调cur,因为需要cur来调整node.next=cur;cur.prev.next=node;node.prev=cur.prev;cur.prev=node;}//查找是否包含关键字key是否在单链表当中public boolean contains(int key) {ListNode cur = head;while (cur != null) {if (cur.var == key) {return true;}cur = cur.next;}return false;}//删除第一次出现关键字为key的节点public void remove(int key) {ListNode cur = head;while (cur != null) {if (cur.var == key) {//头节点if (head.var == key) {head.next.prev = null;head = head.next;return;}//尾巴节点if (last.var == key) {last.prev.next = null;last = last.prev;return;}cur.next.prev = cur.prev;cur.prev.next = cur.next;return;}cur = cur.next;}}//删除所有值为key的节点public void removeAllKey(int key) {ListNode cur = head;while (cur != null) {if (cur.var == key) {//头节点if (head.var == key) {head.next.prev = null;head = head.next;return;}//尾巴节点if (last.var == key) {last.prev.next = null;last = last.prev;return;}cur.next.prev = cur.prev;cur.prev.next = cur.next;}cur = cur.next;}}//得到单链表的长度public int size() {int count = 0;ListNode cur = head;while (cur != null) {cur = cur.next;count++;}return count;}public void display() {ListNode cur = head;for (int i = 0; i < size(); i++) {System.out.print(cur.var + " ");cur = cur.next;}System.out.println();}public void clear() {head = last = null;}
}package demo2;public class IndexNotLegal extends RuntimeException{public IndexNotLegal(){}public IndexNotLegal(String s){super(s);}
}

二、什么是链表

简单来说,像链子一样的数据结构。像火车一节一节车厢一样,每个元素是独立的个体(内部类)。 并且他们在空间里是分散的 

 

为什么分散的还可以找到下一个呢?

答:一个节点里面装着两种东西,一个是值,一个的下一个的地址,这样根据下一个的地址就可以找到下一个了。 

三、链表的分类

常见的链表有三种,但是我这里只介绍两种:无头单链,无头双链。剩下的一种之后再补充。

单链和双链的区别?

答: 一个节点都是一个类。单链装的是值和下个节点双链装的是值和上个节点和下个节点

四、链表的常见操作

插入

怎么插入元素?在链表中很简单! 

单链p下个节点改成n1,n0下个节点改为p。

双链 p下个节点改为n1,n0下个节点改为p(先把p插进去,成一个逆时针),p上个节点改为n0,n1的上个节点改为p(修改原来的两点节点)

注意!还需要考虑一些特殊情况,具体请看代码的实现!

删除 

在链表中删除节点也非常方便,只需改变一个节点的引用(指针)即可。 

单链:n0的下个节点指向n1。

双链:n0下个节点改为n1,n1上个节点改为n0 。

问题来了:为什么p的指向n1可以不删?

答;原因是以及没人指向p了, 如果没人引用(指向)的东西,就会被系统自动回收。 像clear()方法,head不指向首个节点,那么首个节点被回收,同理下面也如此。

五、Java自带的LinkedList 

 两个构造方法

方法解释
LinkedList()无参构造
public LinkedList(Collection c)使用其他集合容器中元素构造List
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);
}

 一些常用方法

方法解释
boolean add(E e)尾插 e
void add(int index, E element)将 e 插入到 index 位置
boolean addAll(Collection 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
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);
// 在起始位置插入0list.add(0, 0); // add(index, elem): 在index位置插入元素elemSystem.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位置的元素设置为elemSystem.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的遍历

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());
//for循环遍历
for (int i = 0; i < list.size(); i++) {System.out.print(list.get(i)+" ");
}
// 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的区别  

不同点数组链表
存储方式连续内存空间分散内存空间
容量扩展长度不可变可灵活扩展
内存效率元素占用内存少、但可能浪费空间元素占用内存多
访问元素O(1)O(N)
添加元素O(N)O(1)
删除元素O(N)O(1)

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

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

相关文章

华媒舍:10种欧洲地区媒体发稿推广技巧

1.了解欧洲地区媒体自然环境必须掌握欧洲地区媒体的发稿推广方法&#xff0c;首先要对欧洲地区媒体自然环境有一定的了解。包含不一样国家的主力媒体&#xff0c;他的阅读者人群、销售市场遮盖及其报导风格等。仅有熟悉媒体自然环境&#xff0c;才能更好的制订营销推广策略。 …

Web----网络通讯部分

一、TCP和UDP的区别 TCP是一种面向连接的协议&#xff0c;它在传输数据之前会建立一条专用的通信连接。这意味着在数据传输过程中&#xff0c;两台计算机之间会有一条稳定的数据传输通道。因此&#xff0c;TCP可以保证数据传输的可靠性&#xff0c;但会带来一定的延迟。 UDP是…

Android VSYNC双Buffer与三Buffer渲染线程RenderThread(5)

Android VSYNC双Buffer与三Buffer渲染线程RenderThread&#xff08;5&#xff09; 手机自带的卡顿丢帧分析工具&#xff0c;柱状图&#xff1a; 帧的大体绘制过程&#xff1a; 帧绘制中的重要概念&#xff1a;BufferQueue 首先看一下 BufferQueue&#xff0c;BufferQueue 是一个…

Visual Studio Code 开发esp8266流程2Arduino 配置 nodemcu

http://arduino.esp8266.com/stable/package_esp8266com_index.json Arduino: Library Manager

第二十五章CSS中的技巧(导航栏、下拉列表)

1.CSS精灵 1.什么是CSS精灵 英文叫法 CSS sprites&#xff0c;通常被解释为“CSS图像拼合”或“CSS贴图定位”;其实就是把网页中一些背景图片整合到一张图片文件中&#xff0c;再利用css“background-image”&#xff0c; “background-repeat”,“background-position”的组…

中国地质大学(武汉):23考研多专业接受调剂,24新增上机考试!中国地质大学(武汉)计算机考研考情分析!

中国地质大学&#xff08;武汉&#xff09;计算机学院成立于1985年&#xff0c;其前身为地矿部武汉计算站。经过近二十年的努力&#xff0c;计算机学院不断发展壮大。现设有计算机应用、计算机软件、网络与系统结构、信息安全四个教研室&#xff1b;拥有湖北省计算机应用技术重…

最大回撤概念与计算

一、最大回撤&#xff0c;是指的最大下跌的值&#xff1a; 1、即所有下跌趋势中&#xff0c;净值最低的点&#xff0c;与历史净值最高点直接的差值。 2、最大回撤取绝对值显示 二、如果有时间限制&#xff0c;则计算对应时间段内的最大回撤。 示意图如下&#xff1a; 三、举…

【Java面试】七、SpringMvc的执行流程、SpringBoot自动装配原理

文章目录 1、SpringMVC的执行流程1.1 视图阶段1.2 前后端分离阶段 2、SpringBoot自动配置原理3、框架常用的注解3.1 Spring的注解3.2 SpringMvc的注解3.3 SpringBoot的注解 4、面试 1、SpringMVC的执行流程 1.1 视图阶段 旧项目中&#xff0c;未前后端分离时&#xff0c;用到…

OAK相机如何将 YOLOv10 模型转换成 blob 格式?

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是Ashely。 专…

Microsoft Fabric 是什么?

最近半个月没有更新内容&#xff0c;原因是什么呢&#xff1f; 原因是花了两周的时间备考了一下"Microsoft Certified: Fabric Analytics Engineer Associate"的考试认证。 非常幸运考试通过了。 那什么是Microsoft Fabric 呢&#xff1f; Microsoft Fabric 是一个…

运筹学_4.整数规划

文章目录 引言4.1 分枝定界方法求解整数规划问题整数规划的分类整数规划解法概述分支定界法 4.2 0-1整数规划0-1整数规划的数学模型隐枚举法求解0-1规划问题 4.3 指派问题(分配问题)的匈牙利解法指派问题的数学模型指派问题的匈牙利解法 引言 规划中的决策变量(全部或部分)限制…

【备战蓝桥杯】蓝桥杯省一笔记:算法模板笔记(Java)

蓝桥杯 0、快读快写模板1、回文判定2、前缀和3、差分4、二分查找5、快速幂6、判断素数7、gcd&lcm8、进制转换9、位运算10、字符串常用API11、n的所有质因子12、n的质因子个数13、n的约数个数14、n阶乘的约数个数15、n的约数和16、阶乘 & 双阶乘17、自定义升序降序18、动…

2024盘古石初赛(服务器部分)

赛后总结 这次初赛就有20道服务器部分赛题&#xff0c;做的情况一般&#xff0c;错了5道题这样&#xff0c;主要原因就是出在第二个网站服务器没有重构起来 今天来复现一下 这次的服务器部分我直接用仿真仿起来就开找了 第一台IM前期配置 先把网配置好&#xff0c;然后ssh…

如此简单,一文带你玩转接口自动化上(Python + Pytest + Requests + Allure )

一. 前言 哈喽大伙们好&#xff0c;好久不见距离上次更新博客已经有一年之久了&#xff0c;这将近一年的时间小编主要的时间都花在了实习和24届校招上面了&#xff0c;最终也是收获满满&#xff0c;选择了一个还不错的offer&#xff0c;感谢一路走来的自己和身边朋友的帮助&…

基于Three.js实现的3D立方体动画

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 基于Three.js实现的3D立方体动画 应用场景 该代码段适用于需要在网页中创建交互式3D场景的场景。例如&#xff0c;可以用于展示产品、创建游戏或制作视觉效果。 基本功能 此代码段使用Three.js库创建了一个…

【机器学习】随机森林:深度解析与应用实践

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 随机森林&#xff1a;深度解析与应用实践引言1. 随机森林基础1.1 什么是随机森林…

Android更新优化 - 增量更新是如何节省用户时间和流量的

增量更新和全量更新 我想玩过大型手游的人都知道&#xff0c;手游的安装包非常大&#xff0c;因为资源图片众多。而你每次更新都把所有文件都更新下来&#xff0c;是非常耗时的&#xff0c;对吧。耗时是一个方面&#xff0c;有些人在户外开的是移动网络&#xff0c;动不动就几…

计算机组成原理·海明编码及其实验

前言&#xff1a;海明编码这一块在刚开始的时候没有弄懂&#xff0c;后面通过做实验、复习慢慢摸清了门道。在学习计算机组成原理的过程中&#xff0c;实验实践是很重要的&#xff0c;它会让你去搞清楚事情背后的原理&#xff0c;逼着你学会你没听懂的东西。这篇文章会从海明码…

Check Point 安全网关任意文件读取漏洞复现(CVE-2024-24919)

Check Point 安全网关任意文件读取漏洞复现(CVE-2024-24919) 1.漏洞描述 Check Point Security Gateways 是 Check Point Sofware 提供的一系列 网络安全Q解决方案。这些解决方案包括下一代防火墙(NGFW)、数据中心安全网关和 A1驱动的量子网关&#xff0c;旨在为企业提供针对…

@Value 读取环境变量配置

在项目开发过程中&#xff0c;有必要使用一些灰色规则&#xff08;即仅用于开发使用过程中的逻辑控制变量&#xff09;。 比如&#xff0c;本地开发中&#xff0c;一些业务逻辑需要调用第三方代码&#xff0c;但又在本地调不通&#xff0c;怎么办。只能通过 if(本地开发) {mock…