数据结构-链表结构-单向链表

链表结构

说到链表结构就不得不提起数据结构,什么是数据结构?就是用来组织和存储数据的某种结构。那么到底是某种结构呢?

数据结构分为:

  • 线性结构
    • 数组,链表,栈,队列
  • 树形结构
    • 二叉树,B树,红黑树等
  • 图形结构
    • 邻接矩阵,邻接表等

那么链表就是我们这节课的主角,之前其实我们都接触过链表就是集合中基于List实现的linkedlist,但是在练习的过程中我发现好多同志只会用,不知道其中原理,知其然而不知其所以然。但是也会有同志说了我会用不就不就醒了,各位凡是要做到精益求精,知其然跟要知其所以然。为实现科技报国我们的祖国就需要这种人才,一起创新创建共创科技大国。

链表结构的定义

什么是链表

在逻辑结构上一个挨一个的数据,但是在实际存储时所在的内存地址却并不连续,相反数据随机分布在内存中的各个位置。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uo1YfDER-1690775932877)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731093517699.png)]

通过数据的指针指向下一个数据,这种存储结构称为链式存储,而这种链式存储所生成的表就是链表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-63Npk2QJ-1690775932878)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731093456452.png)]

链表分类

  • 单向链表
  • 双向链表
  • 双向循环链表

单向链表

什么是单向链表

上面说到了什么是链表,那么在单向链表中我们将数据分为两个区域

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WFVtGpFY-1690775932878)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731095437329.png)]

在链表中它有一个专业名字叫做:节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4HrBVGMO-1690775932879)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731095418610.png)]

一个节点指向下一个节点,这种链式结构称为单向链表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DaVYtHbB-1690775932879)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731095536584.png)]

在单向链表中,链表的第一个节点称为首元节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LVWMVy6h-1690775932880)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731095809932.png)]

链表的最后一个节点称为尾节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RExs1D0C-1690775932880)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731095856557.png)]

中间的这个节点的前一个节点称为前驱

![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h7w71tre-1690775932881)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731100016010.png)](https://img-blog.csdnimg.cn/a07cd1f5d2d74d5f9dfe5dde41da8c4b.png)

中间的这个节点的后一个节点称为后继

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mg6JU2zh-1690775932881)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731100047613.png)]

通常在链表的前面会有一个节点称为头节点,当然头节点不是必须存在的。

  • 头节点的作用是:用来存储链表的长度

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jXLTPxvG-1690775932882)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731100239606.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-29rianmB-1690775932882)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731100320069.png)]

在每一个链表中都会配备一个头指针,指针始终指向第一个节点,如果有链表中配备头节点则指向头节点,如果没有配备头节点则指向首元节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dTTJDnYf-1690775932883)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731100533063.png)]

头指针的定义是:用于在链表中挪动指针查找数据,直到找到对应的数据

在这里插入图片描述

单向链表的功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FPscmp6z-1690775932884)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731103625505.png)]

    • 向链表的尾节点添加节点

      • 将新添加节点的内存地址存放到该链表尾节点的指针域中。通俗的讲:将尾节点的指针域指向新添加的节点

      • 此时尾节点就是新添加的这个节点

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EOecEUmO-1690775932884)(E:\Java笔记\数据结构\线形结构\链表结构.assets\20230731_104622.gif)]

    • 向链表的首元节点之前添加节点

      • 将链表的首元节点的内存地址存放到新添加节点的指针域中。通俗的讲:新节点的指针指向首元节点

      • 此时首元节点是新添加的这个节点

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NGbrG5IA-1690775932885)(E:\Java笔记\数据结构\线形结构\链表结构.assets\20230731_105455.gif)]

    • 向链表中间添加节点

      • 将新添加节点的内存地址存放到前驱的指针域中,新添加节点的指针域存放后继的内存地址。通俗的讲:修改前驱的指针方向指向新添加的节点,新添加的节点执行后继即可

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4JmT2yty-1690775932885)(E:\Java笔记\数据结构\线形结构\链表结构.assets\20230731_110227.gif)]

    • 删除尾节点

      • 尾节点的前驱的指针域不在存储尾节点的内存地址。通俗的讲:尾节点的指针域不在指向尾节点
    • 删除首元节点

      • 首元节点的指针域不存放后继的内存地址。通俗的讲:首元节点的指针与不在指向后继节点
    • 删除中间的某个节点

      • 删除节点的前驱指针域不再存放删除节点的内存地址,删除节点的指针域不再存储后继的内存地址,通俗的讲:删除节点的前驱指向删除节点的后继

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jK3f0kcV-1690775932886)(E:\Java笔记\数据结构\线形结构\链表结构.assets\20230731_110948-16907732210771.gif)]

      注意:被删除的节点称之为:野节点,这并不是真正意义上的删除,它在内存中依旧存在。那么野节点的最终归宿是被JVM的GC(垃圾回收器)所回收,也就是释放该节点的内存空间,这才是真正意义上的删除

      额外知识:java中的垃圾回收器(Garbage Collector,GC)负责管理内存的分配和释放。当一个对象没有任何引用指向它时,它就变得不可达,而垃圾回收器会将其标记为垃圾对象,并在适当的时候回收该对象所占用的内存空间。这个过程称为垃圾回收。

    • 挪动指针找到要修改的节点,之后讲修改节点的数据域中的数据修改掉
    • 挪动指针找到要所要查找的数据。

特点

  • 节点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻。

  • 数据元素的个数可以自由扩充,插入,删除,只需要修改节点的指针方向,效率高

  • 修改和查找节点数据需要挪动指针,按照节点的顺序进行依次查找或者修改,效率比较低

与数组的区别

回顾数组

数组的功能

    • 数据不能超过定义的数组长度
    • 数据少于定义数组的长度会造成内存浪费
    • 数组中间添加数据会将之后的数据内存位置往后挪动

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rbC5fv9m-1690775932886)(E:\Java笔记\数据结构\线形结构\链表结构.assets\20230731_115259.gif)]

区别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kpln7pfQ-1690775932886)(E:\Java笔记\数据结构\线形结构\链表结构.assets\image-20230731115828188.png)]

实现单项链表

MyList
/*** @CreateName SIN* @CreateDate 2023/07/27 16:28* @description 定义链表功能规范,避免子类编码随意性。同时也实现了程序的解耦,提高代码的可维护性。*/
//泛型E任何数据类型
public interface MyList<E> {//添加节点数据void add(E element);//获取节点数据(根据具体的指针找到对应的数据)E get(int index);//获取链表的长度int size();//根据指针移除节点E remove(int index);//修改节点数据E set(int index,E element);
}
MyLinkedList
package com.sin.linkedList;/*** @CreateName SIN* @CreateDate 2023/07/27 16:35* @description*/
public class MyLinkedList<E> implements MyList<E>{// 存放链表的头节点private Node head;// 记录链表的长度private int size;/*** 向链表中添加节点* @param element 添加的节点*/@Overridepublic void add(E element) {//创建一个新的节点,存储传入的元素Node<E> node = new Node<E>(element,null);//获取链表尾节点Node tail = getTail();//如果链表为空,if (tail == null){//将新节点设置为头节点this.head = node;}else{//否则,在尾节点后面添加新节点tail.next = node;}//记录元素的个数this.size++;}/*** 获取尾节点* @return 返回尾节点*/private Node getTail(){//判断当前头节点是否为空if(this.head == null){return null;}//遍历链表//从头节点开始遍历链表Node node = this.head;while (true){//如果下一个节点为空,则表示当前节点为尾节点,则跳出循环if(node.next == null){break;}//在循环的过程中,移动指针,指向下一个节点node = node.next;}//返回尾节点return node;}/*** 根据指针获取节点数据* @param index* @return 返回节点数据*/@Overridepublic E get(int index) {//1,校验index的合法性pointerIndex(index);//2,根据具体位置获取对应的节点数据Node<E> node = getNode(index);//3,将节点中的元素返回return node.item;}/*** 校验所给定的指针是否在链表的有效范围内* @param index*/private void pointerIndex(int index){// 大于等于0并且小于链表长度if (!(index >= 0 && index < this.size)){//获取最大的索引指int a = this.size-1;// 抛出索引越界异常,显示错误信息throw new IndexOutOfBoundsException("你输入的指针为:"+index + "最大指针为:"+a);}}/*** 根据指针获取节点* @return 返回给定索引处的节点*/private Node getNode(int index){//从头节点开始遍历链表Node<E> node = this.head;//移动指针,指向下一个节点,直到所给定的索引位置for (int i = 0;i< index;i++){node = node.next;}//返回给定索引处的节点return node;}@Overridepublic int size() {return this.size;}@Overridepublic E remove(int index) {//校验index的合法性this.pointerIndex(index);//根据index指针找到该节点对象数据Node<E> node = this.getNode(index);//获取该节点对象中的元素E item = node.item;//向该节点对象中单向链表删除//判断当前删除的节点是否为头节点if (this.head == node){this.head = node.next;//如果是删除头节点,头节点的下一个节点,赋值给了头节点}else {Node<E> node1 = this.head;//拿头节点for (int i = 0 ; i<index - 1 ; i++){node1=node1.next;}node1.next = node.next;//将节点的下一个节点赋值给该节点}node.next = null;this.size -- ;//删除成功长度减一return item;//返回元素}/*** 修改节点数据* @param index 挪动指针* @return 返回修好的值*/@Overridepublic E set(int index,E element) {//校验index的合法性pointerIndex(index);//获取index处的节点Node<E> node = getNode(index);//将节点值数据进行赋值替换return node.item = element;}/*** 使用内部类定义单向链表中的节点对象**/class Node<E>{//数据域private E item;//存储的数据//指针域private Node next;//存储下一个节点对象的地址//无参构造方法public Node(){}//全参构造方法public Node(E item,Node next){this.item = item;this.next = next;}}
}
测试
public static void main(String[] args) {MyLinkedList myLinkedList = new MyLinkedList();myLinkedList.add(12);myLinkedList.add(13);myLinkedList.add(14);myLinkedList.add(15);myLinkedList.add(16);System.out.println("根据指针找到值"+myLinkedList.get(4));System.out.println("删除的节点"+myLinkedList.remove(0));System.out.println(myLinkedList);System.out.println(myLinkedList.size());System.out.println(myLinkedList.set(3,"张三");for (int i=0;i<myLinkedList.size(); i++){System.out.print(myLinkedList.get(i)+",");}}

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

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

相关文章

QWidget窗口类

QWidget窗口类 设置父对象窗口位置窗口尺寸窗口标题和图标信号槽函数例子1例子3例子3 设置父对象 // 构造函数 QWidget::QWidget(QWidget *parent nullptr, Qt::WindowFlags f Qt::WindowFlags());// 公共成员函数 // 给当前窗口设置父对象 void QWidget::setParent(QWidget…

Linux系统下MySQL读写分离

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、基于Amoeba读写分离 1.基于程序代码内部实现 2.基于中间代理层实现 三、操作步骤 1.在主机Amoeba上安装java环境 2.安装并配置Amoeba 3.配置Amoeba读写分离…

【大数据趋势】7月30日 汇率,恒指期货的大数据趋势概率分析。

1. 数据源头之一 : 汇率变化 从程序模拟趋势来看&#xff0c;美元在持续弱势状态&#xff0c;周线上正在构建一个新的下跌趋势&#xff0c;而且正在反抽过程中&#xff0c;即将完成&#xff0c;如果没有外部干预&#xff0c;会顺势往下。从月线来看&#xff0c;高点逐步降低&a…

线性代数的学习和整理2:线性代数的基础知识(整理ing)

目录 0 写在前面的话 网上推荐的线性代数的课程 1 线性代数和矩阵的各种概念 1.1 各种逻辑图 2 关于线性代数入门的各种灵魂发问 2.1 什么是线性&#xff0c;什么是线性相关 &#xff1f; 为什么叫线性变换&#xff1f; 为什么叫线性代数&#xff1f; 2.2 线性代数是人造…

Spark性能调优指南来了!

1、什么是Spark Spark 是一种基于内存的快速、通用、可扩展的大数据分析计算引擎。 Spark Core&#xff1a;实现了Spark的基本功能&#xff0c;包含任务调度、内存管理、错误恢复、与存储系统交互等模块。Spark Core中还包含了对弹性分布式数据集(Resilient Distributed Dat…

安科瑞智慧空开微型断路器在银行的应用-安科瑞黄安南

应用场景 智能微型断路器与智能网关组合应用于末端回路 功能 1.计量功能&#xff1a;实时上报电压、电流、功率、电能、漏电、温度、频率等电参量&#xff1b; 2.报警功能&#xff1a;过压报警、欠压报警、过流报警、过载报警、漏电报警、超温报警、三相电缺相报警&#xff…

论文笔记:Adjusting for Autocorrelated Errors in Neural Networks for Time Series

2021 NIPS 原来的时间序列预测任务是根据预测论文提出用一阶自回归误差预测 一阶差分&#xff0c;类似于ResNet的残差思路&#xff1f;记为pred&#xff0c;最终的预测结果

【蓝桥杯备考资料】如何进入国赛?

目录 写在前面注意事项数组、字符串处理BigInteger日期问题DFS 2013年真题Java B组世纪末的星期马虎的算式振兴中华黄金连分数有理数类&#xff08;填空题&#xff09;三部排序&#xff08;填空题&#xff09;错误票据幸运数字带分数连号区间数 2014年真题蓝桥杯Java B组03猜字…

维护电脑,让“战友”保持长寿命

目录 维护电脑&#xff0c;让“战友”保持长寿命介绍你的电脑介绍一下你的日常维护措施给出一些你觉得有用的维护技巧不推荐做些什么其他补充总结 无论是学习还是工作&#xff0c;电脑都是IT人必不可少的重要武器&#xff0c;一台好电脑除了自身配置要经得起考验&#xff0c;后…

Linux内核的I2C驱动框架详解------这应该是我目前600多篇博客中耗时最长的一篇博客

目录 1 I2C驱动整体框架图 2 I2C控制器 2.1 I2C控制器设备--I2C控制器在内核中也被看做一个设备 2.2 i2c控制器驱动程序 2.3 platform_driver结构体中的probe函数做了什么 2.3.1 疑问&#xff1a; i2cdev_notifier_call函数哪里来的 2.3.2 疑问&#xff1a;为什么有两…

2023 ISSE观察:智能遮阳窗帘行业蓬勃发展,AI设计引热议

7月31日&#xff0c;上海国际智能遮阳与建筑节能展览会落下帷幕。作为智能遮阳的行业展会&#xff0c;展会三天&#xff0c;现场热闹非凡&#xff0c;参展商和观展者络绎不绝。 作为一大行业盛事&#xff0c;2023 ISSE展会方打造了五大展区&#xff0c;除了提供系统门窗装修方案…

二、SQL-6.DCL-1).用户管理

一、DCL介绍 Data Control Language 数据控制语言 用来管理数据库 用户、控制数据库的 访问权限。 二、语法 1、管理用户 管理用户在系统数据库mysql中的user表中创建、删除一个用户&#xff0c;需要Host&#xff08;主机名&#xff09;和User&#xff08;用户名&#xff0…

openGauss学习笔记-26 openGauss 高级数据管理-约束

文章目录 openGauss学习笔记-26 openGauss 高级数据管理-约束26.1 NOT NULL约束26.2 UNIQUE约束26.3 PRIMARY KEY26.4 FOREIGN KEY26.5 CHECK约束 openGauss学习笔记-26 openGauss 高级数据管理-约束 约束子句用于声明约束&#xff0c;新行或者更新的行必须满足这些约束才能成…

基于SHARC+®单核的ADSP-21567KBCZ6、ADSP-21566BBCZ4、ADSP-21566KBCZ4高性能DSP处理器产品

ADSP-2156x 处理器的速度高达 1 GHz&#xff0c;属于 SHARC 系列产品。ADSP-2156x 处理器基于 SHARC 单核。ADSP-2156x SHARC 处理器是 SIMD SHARC 系列数字信号处理器 (DSP) 中的一款产品&#xff0c;采用 ADI 的超级哈佛架构。这些 32 位/40 位/64 位浮点处理器已针对高性能音…

Rust vs Go:常用语法对比(九)

题图来自 Golang vs Rust - The Race to Better and Ultimate Programming Language 161. Multiply all the elements of a list Multiply all the elements of the list elements by a constant c 将list中的每个元素都乘以一个数 package mainimport ( "fmt")func …

Android Unit Test

一、测试基础知识 1.1 测试级别 测试金字塔&#xff08;如图 2 所示&#xff09;说明了应用应如何包含三类测试&#xff08;即小型、中型和大型测试&#xff09;&#xff1a; 小型测试是指单元测试&#xff0c;用于验证应用的行为&#xff0c;一次验证一个类。 中型测试是指…

创造自己的宠物医院预约服务小程序,步骤详解

在现代社会&#xff0c;越来越多的人开始养宠物&#xff0c;而宠物的健康管理也成为了一个重要的话题。为了方便宠物主人随时随地进行宠物医院的管理和服务&#xff0c;开发一个宠物医院管理小程序是很有必要的。今天我们将分享一些制作宠物医院管理小程序的技巧&#xff0c;帮…

Vue没有node_modules怎么办

npm install 一下 然后再npm run serve 就可以运行了

基于多任务学习卷积神经网络的皮肤损伤联合分割与分类

文章目录 Joint segmentation and classification of skin lesions via a multi-task learning convolutional neural network摘要本文方法实验结果 Joint segmentation and classification of skin lesions via a multi-task learning convolutional neural network 摘要 在…

Python实现GA遗传算法优化BP神经网络分类模型(BP神经网络分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;最早是由美国的 John holland于20世…