链表的初步认识

news2024/11/15 8:49:45

        什么是链表?链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。 就如现实中的火车或铁链一般,环环相扣。当我们到达一个节点时,就可以通过这个节点找到下一个节点。链表与顺序表一样,都是线性结构,如果你没学过数据结构,那么可能会问,既然有了顺序表,为什么还要链表呢?那是因为它们的作用范围不同,如顺序表它的底层便是一个数组,既然是数组,那么它便不可避免的具有数组的小毛病,那就是不好删除和插入。我猜可能会有人说:“哎哎哎,谁说数组不好删除和插入了,我几个代码就将它给做到了。”,对你来说是几行代码的事情,但是对计算机来说,就得重复n遍了,倘若数组的成员有许多,那么不久拖累了效率了吗?那么有没有一下就能做好这件事的呢?当然有,那就是链表,毕竟你往铁链里面插入一个节点,只需在其位置断开后面的,然后将新的节点接在后面,同时把断下来的部分接在新节点后面就行,而不是如数组一样,将后面一个一个往前面覆盖。

         就连火车都分动铁和高铁等样式,链表自然也多种多样,共有着8种链表。为什么是8种,因为链表有着如下特点,将它们组合起来就只有8种。

1. 单向或者双向
2. 带头或者不带头//所谓头是指该节点
3. 循环或者非循环
虽然有这么多的链表的结构,但是我们重点掌握两种 :
无头单向非循环链表 结构简单 ,一般不会单独用来存数据。实际中更多是作为 其他数据结构的子结构 ,如哈希桶、图的邻接表等等。
无头双向链表 :在 Java 的集合框架库中 LinkedList 底层实现就是无头双向循环链表。
既然我们已经知道了链表的概念,那么我们能不能自己设计链表呢?当然能,并且它还要使用到内部类,并且内部类中要有着一个引用变量,用来指向下一个节点。
内部类:

public class ListNode {

      int val;

      ListNode next;

      ListNode() {}

      ListNode(int val) { this.val = val; }

      ListNode(int val, ListNode next) { this.val = val; this.next = next; }

  }

既然我们知道了什么是链表,那么我们就得学会使用它,不仅要会使用链表,还得学会自己造轮子。那么我们就开始自己写一个链表吧。我写的是无头单向链表。
既然要写一个链表,那么就要知道链表有什么功能,并且它的返回值与传参都要一一考虑,如头插法,我们只需要它要插入的内容就行,因此只需要一个参数,至于是否需要返回值,则根据要求来。当我们全部考虑好后,便只需要填写内容就行。
     //头插法
     public void addFirst(int data);
     //尾插法
     public void addLast(int data);
     //任意位置插入,第一个数据节点为0号下标
     public boolean addIndex(int index,int data);
     //查找是否包含关键字key是否在单链表当中
     public boolean contains(int key);
     //删除第一次出现关键字为key的节点
     public void remove(int key);
     //删除所有值为key的节点
     public void removeAllKey(int key);
     //得到单链表的长度
     public int size();
     public void display();
     public void clear();
头插法应该是最简单的了,我们只需要为要插入的数据创建一个节点,然后将该节点的next指向原来的头节点,然后将头节点重新指向该节点就行。有人或许会问,不是无头的吗?哪来的头节点。所谓的有头无头指的是是否有固定的头节点,若有,则有头,无则无头。
public void addFirst(int value){
        if(this.head == null){
            head = new Node(value);
        }else {
            Node node = new Node(value);
            node.setNext(head);
            head = node;
        }
        size++;//这是用来统计链表的长度的。
    }

而尾插法也与它大同小异,唯一的问题就是如何找到原尾节点在哪。我们要想找到尾节点的话,就要知道它与其它节点的不同,它的后面没有链接任何东西,也就是它的next为空,因此,我们只需遍历整个链表尾节点了,那么怎么遍历呢?我们可以先定义一个变量记录头节点的位置,因为我们要遍历的话,就必然要顺着链条往下走,如果我们不记录头节点的位置,那么头节点的位置也会随着往下走,那岂不是前面的节点都找不到了。因此我们得定义一个变量,当我们定义好后,就该开始遍历了,我们得判断当前变量的next是不是为空,倘若是,则停止遍历,倘如不是,则让该变量指向该变量的next,然后重复以上操作,直到找到尾节点为止。

public void addLast(int value){
        if(this.head == null){
            head = new Node(value);
        }else {
            Node cur = head;
            while (cur.Next != null){
                cur = cur.Next;
            }
            cur.next = new Node(value);
        }
        size++;
    }

展示链表也是通过遍历来进行的,不过是将寻找尾节点的过程中的所有数据都展示出来罢了,而添加也较为简单,我们可以先确定要添加的位置,然后通过双指针遍历找到该位置与该位置的上一个节点,然后与头插法一样,将其添加进去,然后将用双指针找到的该位置的上一个节点的next指向要添加的数据节点,并让该数据节点的next指向原该位置(也通过双指针找到了)。删除也与之大差不差,就不一一写了。那么我们来写我认为是链表中最难的,就是删除所有值为key(我们要删的)的节点,也许有人会说,这也太简单了,只要将删除的操作循环不就行。没错·,这样也行,但这样我们得循环好多次,如果该链表全是我们要删除的,那得循环多少次才行,因此我们得在一次遍历中就将它全部删除。我们还是用双指针来解决,与删除一样,当我们通过快指针找到要删除的节点后,慢指针刚好指向该节点的前一个,然后我们将快指针指向要删除节点的后面,慢指针指向快指针,然后继续遍历,直到快指针为空就全部删除完。

public void removeAll(int value){
        if(head == null){
            return;
        }
        int count = 0;//记录删除节点的个数
        Node prev = head;
        Node cur = prev.next;
        while(cur != null){
            if(cur.data == value){
                count++;
                cur = cur.next;
                if(cur == null){
                    prev.next = null;
                }
                continue;
            }
            prev.next = null;
            prev = cur;
            cur = cur.next;
        }
        if(head.data == value){//如果头节点也要删的话
            head = head.next;
            count++;
        }
        size = size - count;//计算此时链表的长度
    }

剩下的就没太大难度了,就不罗嗦了。

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

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

相关文章

【服务器数据恢复】EXT4文件系统下KVM虚拟机数据恢复案例

服务器数据恢复环境: 服务器采用的Linux操作系统EXT4文件系统; 服务器中有3台KVM虚拟机:一台运行Mysql数据库,一台存放数据库备份,一台存放程序代码文件; 每台虚拟机包含一个qcow2格式的磁盘文件和一个raw格…

联合发版+主题演讲|GBASE南大通用亮相鲲鹏开发者峰会2023

5月6-7日,以“创未来 享非凡”为主题的鲲鹏开发者峰会2023在东莞松山湖举办,旨在打造生态伙伴和开发者学习、共享、交流的平台,帮助开发者深入了解鲲鹏、昇腾全栈技术,加速行业技术、产品和解决方案的创新。行业技术领袖、产业技术…

Apache FtpServer在Windows上使用以及SpringBoot中集成apache ftpserver实现Ftp 服务端搭建

场景 Apache Ftpserver Apache FtpServer是100%纯Java FTP服务器。它被设计为基于当前可用的开放协议的完整且 可移植的FTP服务器引擎解决方案。FtpServer可以作为Windows服务或Unix / Linux守护程序独立运行, 也可以嵌入Java应用程序中。我们还提供…

【图】邻接表

目录 无向图的邻接表 链表(存相邻顶点下标)的类 数组里放的顶点 邻接表(操作) 构造和析构(创建销毁邻接表) 插入顶点 插入边 获取下标 插v1、v2之间的边 删除顶点 删除边 输出: 其他…

多种采购方式下,数智化招采系统解决方案(实例)

广发证券成立于1991年,是国内首批综合类证券公司,先后于2010年和2015年在深圳证券交易所及香港联合交易所主板上市。 多年来,广发证券在竞争激烈、复杂多变的行业环境中努力开拓、锐意进取,以卓越的经营业绩、持续完善的全面风险…

Node.js对ES6 及更高版本的支持

目录 1、简介 2、默认情况下什么特性随着 Node.js 一起发布? 3、有哪些特性在开发中? 4、移除这个标记(--harmony)吗 5、Node.js 对应 V8 引擎 1、简介 Node.js 是针对 V8 引擎构建的。通过与此引擎的最新版本保持同步&…

PMP课堂模拟题目及解析(第5期)

41. 项目的混凝土供应商通知项目经理,材料将比预定时间晚三个星期交付。项目经理更新了进度计划并通知项目团队。在这种情况下,哪种合同类型承担的风 险最小? A. 总价加激励费用合同。 B. 总价加经济价格调整合同。 C. 工料合同。 D. 固…

matlab学习笔记

一、序言 1. 图像的输入输出和显示 fimread("test.png"); frgb2gray(f);%rgb图像转化为灰度图像 imshow(f); imwrite(f,"result.jpg","quality",50);%50代表jpg形式压缩质量0-1002. matlab支持的四种图像类别 灰度级图像(Gray-scale images) …

类和对象【C++】【中篇】

目录 一、类的6个默认成员函数 1、构造函数 2、析构函数 3、拷贝构造函数 4、赋值重载函数 二、赋值运算符重载 一、类的6个默认成员函数 注意:默认成员函数不能在类外面定义成全局函数。因为类里没有的话会自动生成,就会产生冲突。 1、构造函数…

k8s采用ansible安装

一、准备工作 测试服务器 服务器配置进程功能备注192.168.0.189CPU:4核 内存32Gansibleansible一键安装k8s192.168.0.141CPU:12核 内存:10Gdocker,kube-apiserver,etcd,kube-scheduler,kube-controller-m…

产品经理 - 原型图设计软件

原型图设计软件哪个好用?6款好用软件推荐! - 知乎 摩客, 墨刀 2014 即时设计是一款支持在线协作的专业级 UI 设计工具,用户数已突破230万; 2021年 5,000万(美元) 国外 axure 老牌 如果有进一步模拟的必要,再换用Ad…

JetPack之lifecycle原理分析

Lifecycle是什么 Lifecycle可以有效的避免内存泄漏和解决android生命周期的常见难题Livecycle 是一个表示android生命周期及状态的对象LivecycleOwner 用于连接有生命周期的对象,如activity,fragmentLivecycleObserver 用于观察查LifecycleOwnerLifecycle框架使用观…

关于SSL证书有效期缩短,看这一篇就够了

在TLS/SSL证书有效期不断被缩短的大趋势下,我们在前文和大家聊了聊企业面临的困境、应对策略及证书自动化管理,今天想和大家继续探讨的是TLS/SSL证书自动化管理切实可行的解决方案。 01 自动化证书管理的重要性 TLS/SSL证书是保障网络连接安全的重要手…

图片位深度以及转换办法

位图文件的格式: ① 位图文件头,所用结构体:BITMAPFILEHEADER,占14个字节 ② 位图信息头,所用结构体:BITMAPINFOHEADER,占40个字节 ③ 颜色表项,所用结构体:RGBQUAD&…

Qt5.14版本通用环境配置安装——最详细教学(看不懂,你怪我)

✨✨✨大家好,我是会飞的鱼-blog,今天我来给大家介绍一下Qt5.14.1安装,有不足之处,请大家多多指教。感谢大家支持!!! 目录 前言 安装文件下载: 安装: 设置 QtCreator…

测试相关记录

1、提测计划、需求拆分、颗粒度 2、线上bug回顾 3、提测流水线 4、测试业绩合同指定

6.2.4图的基本操作 6.3.1图的广度优先遍历 6.3.2图的深度优先遍历

6.2.4图的基本操作 考研里面只考邻接矩阵和邻接表的存储结构 思想较为简单见video 重点理解时间复杂度的遍历原理 6.3.1图的广度优先遍历(BFS)(Breadth first traversal) 我们从树的广度优先遍历入手去看图的广度优先遍历的思想 …

【Python入门知识】NumPy 中的随机数及ufuncs函数

前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! 什么是随机数? 随机数并不意味着每次都有不同的数字。随机意味着无法在逻辑上预测的事物。 伪随机和真随机 计算机在程序上工作,程序是权威的指令集。 因此,这意味着必须有某种算法来…

2路 QSFP,40G 光纤的数据实时采集(5GByte/s 带宽)板卡设计原理图 -PCIE732

板卡概述 PCIE732 是一款基于 PCIE 总线架构的高性能数据传输卡,板卡具有 1 个 PCIex8 主机接口、2 个 QSFP40G 光纤接口,可以实现 2 路 QSFP 40G 光纤的数据实时采集、传输。板卡采用 Xilinx 的高性 能 Kintex UltraScale 系列 FPGA 作为实时处理器…

【鲁棒优化、无功优化】两阶段鲁棒优化的主动配电网动态无功优化【IEEE33节点】(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…