【单链表】数据结构,详解单链表,java实现代码

news2024/11/23 11:39:25

前言:
大家好,我是良辰丫🍓🍓🍓,今天我和大家一起了解一下数据结构中的链表,链表,顾名思义是用链子把一个个数据串连起了的,那么链表和顺序表又有什么不同呢?我们慢慢往下看。🚀🚀🚀

🧑个人主页:良辰针不戳
📖所属专栏:java数据结构
🍎励志语句:生活也许会让我们遍体鳞伤,但最终这些伤口会成为我们一辈子的财富。
💦期待大家三连,关注,点赞,收藏。
💌作者能力有限,可能也会出错,欢迎大家指正。
💞愿与君为伴,共探Java汪洋大海。


目录

  • 单链表
    • 1.1 单链表的结构
    • 2.2 单链表的基本操作
      • 2.2.1 头插法
      • 2.2.2 尾插法
      • 2.2.3 任意位置插入
      • 2.2.4 查找是否包含关键字key是否在单链表当中。
      • 2.2.5 删除第一次出现关键字为key的节点
      • 2.2.6 删除所有值为key的节点。
      • 2.2.7 得到单链表的长度
      • 2.2.8 清空单链表
      • 2.2.9 打印单链表


单链表

1.1 单链表的结构

链表由一个个节点串起来,其中节点又包括数据域和指针域,节点如下图所示。

在这里插入图片描述

下图为一个简单的单链表图,可能画的不好,嘿嘿嘿,大家见谅哈。其中数据域存放数据,指针域存放下一节点的地址,通过地址就可以间接访问下一节点。

在这里插入图片描述

2.2 单链表的基本操作

接下来我们就来搞一下单链表的基本操作,让大家更加深刻的了解链表。一般而言,我们经常使用无头的链表,我们今天就拿无头的链表进行举例。注意我们说的头节点是傀儡节点,就是它不存储链表的数据,只是一个哨兵作用。

2.2.1 头插法

先实例化一个新节点。

在这里插入图片描述

新节点与单链表建立联系。

在这里插入图片描述

head指向新的头结点。

在这里插入图片描述

大家看了上面的单链表头插法是不是感觉没那么难呢?嘿嘿嘿,只要找到了规律,其实一切都不是那么难。现在呢,大家需要记住一个先绑定后面的思想,这样防止前面链条断了无法串连起来链表。

public void addFirst(int data){
        ListNode listNode = new ListNode(data);
        listNode.next = head;
        head = listNode;
    }

2.2.2 尾插法

  • 同样也是先申请一个头结点,注意,数据结构是很严谨的,需要把很多情况都考虑到。
  • 头结点为空,说明链表没有元素,插入元素的节点直接成为了头结点。
  • 链表尾插法的空间复杂度为O(n),需要去遍历找到尾巴,才可以进行插入,相比于顺序表,不用担心它的容量不足。

在这里插入图片描述

尾节点与新节点进行连接。

在这里插入图片描述

public void addLast(int data){
        ListNode listNode = new ListNode(data);
        if(head == null) {
            head = listNode;
            return;
        }
        ListNode cur = head;
        while (cur.next != null) {
            cur = cur.next;
        }
        cur.next = listNode;
    }

2.2.3 任意位置插入

  • 插入的位置如果不合法,直接抛出异常(但是在牛客网等做题网站不能这样,会被当做错误处理)。
  • 在首位置插入元素,直接调用头插法,在尾位置插入元素,直接调用尾插法。
  • 如果是在中间进行插入,找到要插入的前一个位置,这里我们用cur进行遍历,先进行右边绑定,然后再连接左边。

在这里插入图片描述

public void addIndex(int index,int data)
            throws ListIndexOutOfException{
        checkIndex(index);
        if(index == 0) {
            addFirst(data);
            return;
        }
        if(index == size()) {
            addLast(data);
            return;
        }
        ListNode cur = findIndexSubOne(index);
        ListNode listNode = new ListNode(data);
        listNode.next = cur.next;
        cur.next = listNode;
    }
private ListNode findIndexSubOne(int index) {
        ListNode cur = head;
        int count = 0;
        while (count != index-1) {
            cur = cur.next;
            count++;
        }
        return cur;
    }
    private void checkIndex(int index) throws ListIndexOutOfException{
        if(index < 0 || index > size()) {
            throw new ListIndexOutOfException("index位置不合法");
        }
    }

2.2.4 查找是否包含关键字key是否在单链表当中。

这个也是一个简单的遍历,找到关键字,返回true,否则就返回false。

public boolean contains(int key){
        ListNode cur = head;
        while (cur != null) {
            if(cur.val == key) {
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

2.2.5 删除第一次出现关键字为key的节点

  • 如果链表没有数据,直接return。
  • 如果头结点的数据与关键字相同,头结点直接后移一位。
  • 找到要删除节点的前驱节点,没有要删除的节点返回空。
  • 直接cur.next = del.next,有的小伙伴可能会有疑问,一个指令就可以删除嘛。那么它原来的指向呢?就像给变量赋值,cur.next给它赋予了新的指向,del.next或许还指向地址为0x112的节点,但是在访问链表的时候已经访问不到del的节点,如果大家觉得不合适可以把del.next置为空。

在这里插入图片描述

 public void remove(int key){
        if(head == null) {
            return ;//一个节点都没有
        }
        if(head.val == key) {
            head = head.next;
            return;
        }
        ListNode cur = searchPrev(key);
        if(cur == null) {
            return;
        }
        ListNode del = cur.next;//要删除的节点
        cur.next = del.next;
    }
    //找到要删除的前驱节点
    private ListNode searchPrev(int key) {
        ListNode cur = head;
        while (cur.next != null) {
            if(cur.next.val == key) {
                return cur;
            }
            cur = cur.next;
        }
        return null;//没有你要删除的节点
    }

2.2.6 删除所有值为key的节点。

  • 删除所有值为key的节点,这里我们使用双指针思想。
  • 头结点为空时直接退出,让prev指向头结点,cur指向head.next,然后进行遍历,找到关键字的时候就进行上面的删除操作,如果没有找到,指针后移,直到遍历完链表。
public void removeAllKey(int key){
        if(head == null) {
            return;
        }
        /*while(head.val == key) {
            head = head.next;
        }*/
        ListNode prev = head;
        ListNode cur = head.next;
        while (cur != null) {
            if(cur.val == key) {
                prev.next = cur.next;
                cur = cur.next;
            }else {
                prev = cur;
                cur = cur.next;
            }
        }
        if(head.val == key) {
            head = head.next;
        }
    }
   

2.2.7 得到单链表的长度

通过遍历记录单链表长度。

//得到单链表的长度 O(N)
    public int size(){
        int count = 0;
        ListNode cur = head;
        while (cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

2.2.8 清空单链表

单链表是通过头结点进行遍历的,头结点置为空时就找不到后面的节点了。

 public void clear() {
        head = null;
    }

2.2.9 打印单链表

遍历打印单链表。

public void display() {
        //如果说 把整个链表 遍历完成 那么 就需要 head == null
        // 如果说 你遍历到链表的尾巴  head.next == null
        ListNode cur = head;
        while (cur != null) {
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
        System.out.println();
    }

后序:
今天的单链表就讲到这里,希望大家有一定的收获,以路为马,不负韶华,朝着新的彼岸前行,加油。💞💞💞

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

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

相关文章

mysql存储过程基本语法

本文来说下mysql存储过程基本语法 文章目录基本语法使用实例变量的使用变量定义declare语句变量赋值用户变量存储过程的参数in 输入参数out 输出参数inout输入输出参数本文小结基本语法 存储过程就是具有名字的一段代码&#xff0c;用来完成一个特定的功能。创建的存储过程保存…

2022年全球白帽常用工具排行榜TOP 10

虽然此时还未到2022年年底&#xff0c;但并不妨碍我们整理一份2022年全球白帽常用的工具榜单&#xff0c;希望能给白帽们和企业安全人员们带来一定的借鉴和参考。 一方面&#xff0c;工具的重要性不言而喻&#xff0c;各大SRC的白帽们也有深刻的切身体会。一个好用且靠谱的工具…

带模糊加工时间的柔性作业车间调度理论和GA复现(python)

文章目录1.模糊作业车间1.1 模糊数1.2 三角模糊数操作1.3 模糊甘特图2.FJSP模糊加工时间GA2.1 GA算法设置2.2 python代码2.3 测试结果1.模糊作业车间 1.1 模糊数 论域X上的模糊集合A由隶属度函数u(x)表示&#xff0c;u(x)取值[0,1]。如果A为三角模糊数&#xff0c;A可以表示为…

软件测试复习07:软件测试过程

作者&#xff1a;非妃是公主 专栏&#xff1a;《软件测试》 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录测试计划测试设计测试执行测试监控测试结束软件测试过程主要有5个阶段&#xff1a;测试计划、测试设…

《深入浅出计算机组成原理》学习笔记 Day3

ELF和静态链接1. 程序执行&#xff1a;编译、链接和装载2. ELF 格式和链接3. 总结延伸参考1. 程序执行&#xff1a;编译、链接和装载 有这么两个C文件&#xff1a; \\ add.c int add(int a, int b) {return a b; }\\ test.c #include <stdio.h> int main() {int a 1;…

JVM学习(三):聊聊内存泄漏(memory leak)

一、什么是内存泄漏&#xff08;memory leak&#xff09;可达性分析算法来判断对象是否是不再使用的对象&#xff0c;本质都是判断一个对象是否还被引用。那么对于这种情况下&#xff0c;由于代码的实现不同就会出现很多种内存泄漏问题&#xff08;让JVM误以为此对象还在引用中…

最新光速配置VScode运行C/C++教程(W11适用)

文章目录1.下载MingW编译器&#xff1a;2.解压7z压缩文件方法3.VScode配置4.下面看看成果&#xff1a;1.下载MingW编译器&#xff1a; 下载地址 往下面拖找到上面这个东西-下载最新版本 2.解压7z压缩文件方法 7z解压程序官网 下它&#xff01;相信这个时候在装的一般都是6…

【ubuntu | cuda】ubuntu22.04 安装cuda11.3方法

every blog every motto: You can do more than you think. 0. 前言 ubuntu22.04 安装cuda11.3方法记录 1. 正文 1.1 方法一&#xff1a; https://developer.nvidia.com/cuda-11.3.0-download-archive?target_osLinux&target_archx86_64&DistributionUbuntu&…

服务网格领域的百花齐放,是否存在一个更优解?

作者lingsamuel&#xff0c;API7.ai 云原生技术专家&#xff0c;Apache APISIX Committer。 作者林志煌&#xff0c;API7.ai 技术工程师&#xff0c;Apache APISIX contributor。 服务网格是一种技术架构&#xff0c;它用于管理微服务系统中各个服务之间的通信&#xff0c;旨在…

关于volatile和gcc 优化的的思考

volatile是一个特征修饰符&#xff08;type specifier&#xff09; volatile的作用是作为指令关键字&#xff0c;确保本条指令不会因编译器的优化而省略&#xff0c;且要求每次直接读值。这是百度百科的介绍&#xff0c;那编译器是具体是怎么优化的呢。我们知道gcc 是有O0 O1 O…

torch.nn.MSELoss扒开看看它

目录官网介绍Toy默认参数定制参数预测问题-线性回归官网介绍 Toy 设X,Y∈Rnd\mathbf{X} , \mathbf{Y} \in \mathbf{R}^{n\times d}X,Y∈Rnd&#xff0c;假设其中X\mathbf{X}X是模型的输入&#xff0c;Y\mathbf{Y}Y是真实标签 默认参数 torch.nn.MSELoss(size_averageNone, r…

【Java IO流】字节流详解

文章目录1. IO 流概述2. IO 流分类3. 字节输出流4. 字节输入流5. 文件拷贝6. IO 流中的异常处理7. 总结Java编程基础教程系列1. IO 流概述 什么是 IO 流&#xff1f; IO 流是存取数据的解决方案&#xff0c;在计算机中数据存放在硬盘的文件中&#xff0c;如果程序需要使用这些…

Gitlab 项目上传到Maven仓库

Gitlab 项目上传到Maven仓库Gitlab 项目上传到Maven仓库1. 生成Deploy tokens2.项目工程AS的build.gradle配置Maven3. 拉取Maven库Gitlab 项目上传到Maven仓库 1. 生成Deploy tokens 项目地址-》Settings-》Repository-》Deploy tokens-》Expand-》输入Name-》Create deploy …

回收租赁商城系统功能拆解10讲-会员等级

回收租赁系统适用于物品回收、物品租赁、二手买卖交易等三大场景。 可以快速帮助企业搭建类似闲鱼回收/爱回收/爱租机/人人租等回收租赁商城。 回收租赁系统支持智能评估回收价格&#xff0c;后台调整最终回收价&#xff0c;用户同意回收后系统即刻放款&#xff0c;用户微信零…

数据分析面试题--SQL面试题

目录标题1&#xff0c;UNION和JOIN的区别2&#xff0c;连续登录问题3&#xff0c;窗口函数和普通聚合函数的区别4&#xff0c;窗口函数的基本用法5&#xff0c;序号函数:row_number(),rank(),dense_rank()的区别6&#xff0c;窗口函数涉及的一些其他函数7&#xff0c;次日留存率…

CAD软件中如何标注曲线长度?

在CAD设计过程中&#xff0c;如果想要用CAD标注图纸中某一曲线的长度该如何操作呢&#xff1f;今天小编就来给大家分享一个CAD标注曲线长度的小工具&#xff0c;有需要的小伙伴可以一起来看看哦&#xff01; 此插件可以用多种方式标注多段线、样条曲线的长度&#xff0c;并可以…

Go语言笔记:UDP基础使用与广播

文章目录目的基础说明作为服务器使用作为客户端使用广播总结目的 UDP是比较基础常用的网络通讯方式&#xff0c;这篇文章将介绍Go语言中UDP基础使用的一些内容。 本文中使用 Packet Sender 工具进行测试&#xff0c;其官网地址如下&#xff1a; https://packetsender.com/ 基…

知识站点上关于Notes Domino话题几个问答

大家好&#xff0c;才是真的好。 今天周一我们继续不讲技术&#xff0c;介绍一下知识网站上关于Notes/Domino几个有趣问题的讨论。 国内的知识网站头把交椅是知乎&#xff0c;在中文界中是扛把子.不过在国外&#xff0c;最流行的知识网站叫做Quora&#xff0c;上面关于Notes/…

【Java】【系列篇】【Spring源码解析】【三】【体系】【PostProcessors体系】

PostProcessor英文翻译为后置处理器&#xff0c;在Spring体系里面主要针对的对象为Bean和BeanFactory.有着收尾或完善的作用。一、BeanPostProcessor分支 1.1、作用 在Bean对象在实例化和依赖注入完毕后&#xff0c;在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean…

【学习笔记】【Pytorch】十六、模型训练套路

【学习笔记】【Pytorch】十六、模型训练套路一、内容概述二、模型训练套路1.代码实现&#xff1a;CPU版本2.代码实现&#xff1a;优先GPU版本a3.代码实现&#xff1a;优先GPU版本b4.计算测试集上的正确率三、使用免费GPU训练模型一、内容概述 本内容主要是介绍一个完整的模型训…