图解链表 —— JAVA中的单链表基本操作
文章目录
- 1. 什么是链表
- 2. 链表的种类
- 3. 创建单链表
- 3.1 创建 Node 类(车厢类)
- 3.2 创建 MySingleList (火车类)
- 4. 单链表的基本操作
- 4.1 增加链表元素
- 4.1.1 在链表头部添加元素
- 4.1.2 在链表任意位置添加元素
- 4.1.3 在链表尾部添加元素
- 4.2 删除链表元素
- 4.2.1 删除第一个节点元素
- 4.2.2 删除任意位置 index 元素
- 4.2.3 删除链表中指定元素的第一个节点
- 4.2.4 删除链表的所有指定元素
- 4.3 查找链表元素
- 4.3.1 判断链表中是否包含元素 data
- 4.3.2 得到链表中 index 位置的元素
- 4.4 修改链表元素
- 4.5 打印链表
1. 什么是链表
链表是一种物理存储结构上非连续的存储结构,是线性表的一种。
使用链表的原因:链表和顺序表同属于一种线性表但是顺序表有扩容浪费空间,以及中间位置插入元素和删除元素需要移动大量的数据效率低的缺点,使用链表则可以解决这些问题。
2. 链表的种类
- 单向,双向
- 带头,不带头
- 循环,非循环
重点掌握:无头单向非循环链表,一般是配合其他数据结构使用,如哈希桶,图等等;另一个就是无头双向链表。
3. 创建单链表
单链表由两个类组成,一个类用来存储单链表中节点的元素以及指向下一个节点的地址,相当于现实社会中的火车车厢,每节车厢通过铁链相连,铁链相当于指向下一个节点的地址,只有知道地址才能使两个节点相连。每节车厢存放不同的物品就是节点中的元素。有了车厢才能组成一辆火车,所以另一个类就是火车类,存储的是单链表中实际存储的元素和单链表的头节点。
3.1 创建 Node 类(车厢类)
/*** 车厢类*/
public class Node {// 存储具体元素int data;// 存储下一个节点的地址Node next;public Node(int data) {this.data = data;}public Node(int data, Node next) {this.data = data;this.next = next;}
}
3.2 创建 MySingleList (火车类)
public class MySingleList {// 链表中的实际存储元素private int size;// 链表中的头节点private Node head;
}
4. 单链表的基本操作
4.1 增加链表元素
4.1.1 在链表头部添加元素
public void firstAdd(int data) {// 关注临界条件// 1.链表中有没有节点,判空// 2.链表中已经有节点了if (size == 0) {// 1. 先创建一个新节点存放 data 值Node node = new Node(data);// 2. 头节点变为新加入的节点head = node;size++;} else {// 1. 先创建一个新节点存放 data 值Node node = new Node(data);// 2. 将新节点与原来的第一个节点连接node.next = head;// 3. 将头节点变为新的节点head = node;size++;}}
图解:
4.1.2 在链表任意位置添加元素
在 index 位置插入新节点要先找到前驱节点,为什么找前驱节点,因为单链表特点是只能从前往后遍历,所以要在任意位置添加节点要先知道它的前驱节点。添加步骤:先要使新节点与原来该位置的节点相连,并且将原来的前驱节点与新节点相连,这样就添加成功了。
public void indexAdd(int index, int data) {// 边界条件:1. 链表是否为空 2. 索引是否合法 3. index 是否是第一个节点// 1. 链表是否为空if (size == 0) {System.err.println("链表为空!");} else if (index < 0 || index > size) { //2. 索引是否合法System.err.println("索引非法!");} else if (index == 0) { // 3. index 是否是第一个节点firstAdd(data);} else {Node node = new Node(data);// 前驱节点Node prev = head;// 遍历找到 index 的前驱节点for (int i = 0; i < index - 1; i++) {prev = prev.next;}// 先将 index 位置的节点与插入的节点连接,index 位置的节点就是 prev.nextnode.next = prev.next;// 再将插入的节点与前驱节点连接prev.next = node;size++;}}
图解:
4.1.3 在链表尾部添加元素
public void lastAdd(int data) {indexAdd(size,data);size++;}
4.2 删除链表元素
在单链表中遇到 index 都需要判断索引是否合法,所以可以将判断索引是否合法这个方法提出来。
// 索引是否合法private boolean rangeCheck(int index) {if (index < 0 || index >= size) {System.err.println("索引非法!");return false;}return true;}
4.2.1 删除第一个节点元素
public void deleteFirst() {// 创建一个临时变量存放 headNode node = head;// 将头节点从第一个变为第二个head = head.next;// 将原来的第一个节点断开node.next = null;size--;}
图解:
4.2.2 删除任意位置 index 元素
public void deleteIndex(int index) {// 边界条件:1. 链表为空 2. 索引合法 3. 删除的是第一个节点// 1. 链表为空if (size == 0) {System.out.println("链表为空!");// 2. 索引合法} else if (rangeCheck(index)) {// 3. 删除的是第一个节点if (index == 0) {deleteFirst();} else {// 暂存 head 节点Node prev = head;for (int i = 0; i < index; i++) {prev = prev.next;}// prev 指向待删除节点的前驱节点// node 就是待删除节点Node node = prev.next;// 链接前驱节点和后继节点prev.next = node.next;// 将当前 node 节点的 next 置为空,断开待删除元素和链表的链接node.next = null;size--;}}}
图解:
4.2.3 删除链表中指定元素的第一个节点
public void deleteDataOnce(int data) {if (size == 0) {System.out.println("链表为空!");} else {// 临界条件:指定元素在头节点if (head.data == data) {deleteFirst();} else {Node prev = head;while (prev.next != null) {// 如果 prev.next 是指定元素if (prev.next.data == data) {// 创建 node 放指定元素的节点Node node = prev.next;// 将 prev.next 指向 prev.next.next,跳过 nodeprev.next = node.next;// 将 node 与链表断开node.next = null;size--;break;} else {// 如果 prev.next 不是指定元素,继续判断下一个prev = prev.next;}}}}}
图解:
4.2.4 删除链表的所有指定元素
public void deleteAll(int data) {// 临界条件:指定元素是第一个节点// head != null 链表中的元素都相同,如果一直删除会出现链表为空,不能继续往下判断while (head != null && head.data == data) {deleteFirst();}// 链表都是待删除的节点且已经被删除完了if (head == null) {return;} else {Node prev = head;while (prev.next != null) {if (prev.next.data == data) {// node 就是待删除节点Node node = prev.next;prev.next = node.next;node.next = null;size--;} else {prev = prev.next;}}}}
图解:
4.3 查找链表元素
4.3.1 判断链表中是否包含元素 data
public boolean contains(int data) {Node node = head;while (node != null) {if(node.data == data) {// System.out.println("链表中包含该元素");return true;}node = node.next;}
// System.out.println("链表中没有该元素");return false;}
4.3.2 得到链表中 index 位置的元素
public int get(int index) {if(rangeCheck(index)) {Node node = head;for (int i = 0; i < index; i++) {node = node.next;}// node.data 就是 index 位置的元素int data = node.data;return data;}else{// 索引不合法return -1;}}
4.4 修改链表元素
public void set(int index, int data) {if(rangeCheck(index)) {Node node = head;for (int i = 0; i < index; i++) {node = node.next;}// 将原来 index 位置的元素修改成 datanode.data = data;} else{System.out.println("索引非法");}}
4.5 打印链表
public String toString() {String result = "";// 创建一个新节点存放头节点防止遍历完链表找不到链表的头Node node = head;while (node != null) {result += node.data + "->";node = node.next;}// 如果链表为空,引用类型的默认值为 nullresult += "null";return result;}
总结:1. 链表中无论是添加还是删除操作如果参数中有索引,都需要注意索引是不是链表中的头节点,因为头节点比较特殊,它没有前驱节点。2. 使用索引时还需要注意索引是否合法即 index < 0 || index >= size 索引不合法。这点与之前顺序表有所不同,因为顺序表可以在最后扩容所以 index 可以等于 size。
图解链表 —— JAVA中的单链表基本操作相关推荐
- 浅谈:数据结构之单链表,java代码演示单链表
单链表 本文是观看尚硅谷韩老师视频学习总结,部分来源网络. 单链表介绍 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每 ...
- java中建立单链表_Java数据结构,单链表的建立
import java.util.*; //学生类 class Stu { private int math;//学生的学号 private String name;//学生的名字 public St ...
- PHP数据结构之三 线性表中的单链表的PHP实现
线性表的链式存储:用一组任意的存储单元存储线性表中的数据元素.用这种方法存储的线性表简称线性链表. 链式存储线性表的特点:存储链表中结点的一组任意的存储单元可以是连续的,也可以是不连续的,甚至是零散分 ...
- 链表的特点,单链表的定义、存储结构,单链表的基本操作(判断链表是否为空、销毁链表、清空链表、求链表表长、查找、插入、删除,建立单链表)
目录 一.链表(链式存储结构)的特点 二.单链表的定义和表示 1.带头结点的单链表 2.单链表的存储结构 三.单链表基本操作的实现 1.单链表的初始化(带头结点的单链表) 2.补充单链表的几个常用简单 ...
- java语言实现单链表---不含头结点
java语言实现单链表---不含头结点 一.相关概念 1.什么是线性表 2.什么是顺序表 3.什么是链表 4.单链表.双链表.循环单链表.循环双链表 5.头结点和首结点 6.常见的栈和队列与线性表的关 ...
- Java数据结构——用单链表编写一个简易通讯录
Java数据结构--用单链表编写一个简易通讯录 1.定义线性表的抽象数据类型(接口) 2.定义单链表的结点Node类 3.定义数据域中的联系人Person类 4.编写顺序表(类) 5.编写测试程序(m ...
- java集合—— 链表(java中的所有链表都是双向链表)
[0]README 0.1) 本文描述转自 core java volume 1, 源代码 diy 的, 旨在理解 java集合-- 链表(java中的所有链表都是双向链表) 的相关知识: 0.2) ...
- 删除链表的中间节点 Java实现_【链表问题】删除单链表的中间节点
前言 以专题的形式更新刷题贴,欢迎跟我一起学习刷题,相信我,你的坚持,绝对会有意想不到的收获.每道题会提供简单的解答,如果你有更优雅的做法,欢迎提供指点,谢谢. [题目描述] 给定链表的头节点head ...
- java 链表逆转_java 实现单链表逆转详解及实例代码
java 实现单链表逆转详解 实例代码: class Node { Node next; String name; public Node(String name) { this.name = nam ...
最新文章
- 【 FPGA 】组合逻辑中的竞争与险象问题(四)
- 括号匹配(栈和队列)
- H. Fight Against Monsters
- Django进阶Model篇—数据库操作(ORM)
- 弹簧触摸开关原理图_10年老电工经验之谈:常见的开关电源那些事儿
- Windows Azure Marketplaces上的Bing Search API可用啦!
- 开源TinyXML 最简单的新手教程
- 关于std::set的一些补充
- RR调度(Round-robin scheduling)简单介绍
- 从输入URL到页面加载的全过程
- iOS 中的正则匹配(工具类方法)
- matlab出图时汉字都变成方框_Autodesk软件界面中文字都变成符号“方框”,怎么办呢?...
- 快逸报表整合至MyEclipse项目中
- 基于TCP协议的电子词典
- ESB 分布式处理技术 Remoting
- 精密制造业行业_精密制造业的发展:精密制造业的深度报告
- 汽车驾驶技巧-倒车入库技巧图解-怎样倒车入库
- 用Requests下载百度一页图片,以下载芳心纵火犯为例
- 《Learn to Augment: Joint Data Augmentation and Network Optimization for Text》
- 华为p20何时升级成鸿蒙,华为P20用户须知!EMUI 9.1 正式推送更新
热门文章
- Docker学习(一):基础理论基础操作
- matlab噪音的消除办法,基于MATLAB的噪声消除方法.ppt
- 百度网盘青春版将不限速;Win10商店上线摸鱼App;Log4j维护者:只有三个人赞助Log4j项目 | EA周报...
- 桂林山水甲天下,阳朔山水甲桂林
- 微信公众平台搭建与开发揭秘
- 配置网站的快捷方式图标及收藏图标
- 应用程序错误电脑黑屏_电脑运行程序出现APPCRASH错误的三种解决方法
- 沉溺于成为资深Java程序员的危机
- cosbench - 对象存储性能压力测试工具
- CST微波工作室学习笔记2 主要特点