Java数据结构与算法--链表(Linked List)

  • 博客主页:誓则盟约
  • 系列专栏:Java SE
  • 关注博主,后期持续更新系列文章
  • 如果有错误感谢请大家批评指出,及时修改
  • 感谢大家点赞👍收藏⭐评论✍ 

深入了解链表:

        链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的链接(指针),但是在Java中没有指针这个说法,我们称其为引用

链表的主要特点包括:

  1. 动态性

    • 可以在运行时方便地添加或删除节点,无需事先确定链表的大小。
    • 例如,在需要不断添加新用户信息的场景中,链表能够灵活适应数据量的变化。
  2. 内存分配

    • 节点在内存中可以不连续存储,这与数组不同。
    • 使得链表能够更有效地利用内存空间。

链表分为多种类型,常见的有:

   1.单链表

  • 每个节点只有一个指向下一个节点的指针。
  • 从头到尾进行遍历。
  • 例如,实现一个简单的任务队列,新任务添加到链表尾部,处理任务从头部开始。

    2.双向链表

  • 节点既有指向前一个节点的指针,也有指向下一个节点的指针。
  • 可以双向遍历,在查找特定节点时可能更高效。

    3.循环链表

  • 尾节点的指针指向头节点,形成一个环。

链表的操作主要包括:

1.插入节点

  • 可以在头部、尾部或中间位置插入。

2.删除节点

  • 根据特定条件删除指定节点。

3.查找节点

  • 通常需要从链表的头部或尾部开始逐个遍历。

链表的一些缺点:

1.访问效率低

  • 要访问特定位置的节点,需要从头开始遍历,时间复杂度较高。

2.额外的指针存储空间

  • 每个节点都需要存储指针,增加了存储开销。

        总之,链表在许多场景中发挥着重要作用,特别是当需要频繁进行插入和删除操作,且对随机访问要求不高时,链表是一种非常合适的数据结构选择。下面主要介绍的是单链表:


链表的节点类设计:

      这里采用私密的静态类方法定义Node,由于不知道element是什么类型,这里照样使用泛型,代码实现如下: 

    private static class Node<E> {private E e;private Node<E> next;public Node(E e) {this.e = e;}}

        定义一个链表对象:

public class LinkedList<E> {private Node<E> head = new Node<>(null) ;private  int size;

链表的添加方法:

在指定位置(index)处插入一个结点(node),只需要两步即可:

  • 可以先修改插入的结点的后继结点(也就是下一个结点)指向,指向原本在这个位置的结点:

  • 接着我们可以将前驱结点(也就是上一个结点)的后继结点指向修改为我们新插入的结点:

这样,我们就成功的插入了一个新的结点,现在新插入的结点到达了原本的第二个位置上:

按照这个思路,我们只需要找到index指向的这个节点,即可完成插入,代码实现如下:

public class LinkedList<E> {private Node<E> head = new Node<>(null);  // 初始化头节点,值为 nullprivate int size;  // 记录链表中元素的数量/*** 在指定索引处添加元素* @param e 要添加的元素* @param index 元素要添加的索引位置*/public void add(E e, int index) {if (index < 0 || index > size) throw new IndexOutOfBoundsException();  // 检查索引是否越界,越界则抛出异常Node<E> prev = head;  // 从头部开始for (int i = 0; i < index; i++) {  // 找到指定索引位置的前一个节点prev = prev.next;}Node<E> node = new Node<>(e);  // 创建新节点node.next = prev.next;  // 新节点的 next 指向原索引位置的节点prev.next = node;  // 前一个节点的 next 指向新节点size++;  // 链表元素数量加 1}
}

链表的删除方法:

        插入操作完成之后,我们接着来看删除操作,删除操作就更简单了,可以直接将待删除的结点的前驱结点指向修改为待删除节点的下一个:

        这样,理论上来说,待删除结点就已经不在链表中了,所以我们只需要释放掉结点所占用的内存空间(JVM会自动回收)就可以了:

代码实现:

public E remove(int index) {if (index <0 || index > size-1) throw new IndexOutOfBoundsException();Node<E> prev = head;for (int i = 0; i < index; i++) {prev = prev.next;}E e = prev.next.e;prev.next = prev.next.next;return e;}

链表的get方法:

        要像列表一样访问指定的index下标的元素,在单链表中只能一个一个往后找(时间复杂度O(n)),会比顺序表(O(1))复杂度高很多。代码实现:

  public E get(int index) {if (index <0 || index > size-1) throw new IndexOutOfBoundsException();Node<E> node = head;for (int i = 0; i < index; i++) {node = node.next;}return node.e;}public int size() {return size;}

链表的转字符串输出方法:

        链表本身不能直接输出,要想以特定的方式输出一个链表,就需要去定义一个toString方法,下面是一个简单的代码示例:

public String toString() {StringBuilder sb = new StringBuilder();Node<E> node = head.next;while (node != null) {sb.append(node.e).append("  ");node = node.next;}return sb.toString();
}

完整代码实现单链表:

import org.w3c.dom.Node;public class LinkedList<E> {private Node<E> head = new Node<>(null) ;private  int size;public void add(E e,int index) {if (index <0 || index > size) throw new IndexOutOfBoundsException();Node<E> prev = head;for (int i = 0; i < index; i++) {prev = prev.next;}Node<E> node = new Node<>(e);node.next = prev.next;prev.next = node;size++;}private static class Node<E> {private E e;private Node<E> next;public Node(E e) {this.e = e;}}public E remove(int index) {if (index <0 || index > size-1) throw new IndexOutOfBoundsException();Node<E> prev = head;for (int i = 0; i < index; i++) {prev = prev.next;}E e = prev.next.e;prev.next = prev.next.next;return e;}public E get(int index) {if (index <0 || index > size-1) throw new IndexOutOfBoundsException();Node<E> node = head;for (int i = 0; i < index; i++) {node = node.next;}return node.e;}public int size() {return size;}
public String toString() {StringBuilder sb = new StringBuilder();Node<E> node = head.next;while (node != null) {sb.append(node.e).append("  ");node = node.next;}return sb.toString();
}
}

“戒除欲望,控制行为,充实生活,美好的世界。”——《yuanziyu》

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

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

相关文章

jdk版本区别

JDK&#xff08;Java Development Kit&#xff09;是 Java 开发工具包&#xff0c;它包括了 Java SE&#xff08;Standard Edition&#xff09;、编译器、调试器和其他开发工具。Oracle 公司是 JDK 的主要供应商&#xff0c;它提供了多个版本的 JDK&#xff0c;每个版本都有自己…

SQLException:Operation not allowed after ResultSet closed

运行代码时出现的错误&#xff1a; 这是在运行简单的JDBC访问数据库时出现的问题&#xff0c;原因是在ResultSet方法中添加了close()关闭方法,如图&#xff1a; ResultSet 是通过 query 方法获得的&#xff0c;并且在 try-catch 块中没有显式地关闭它。这实际上是 一个常见的…

暴雨宅家?AI拯救你的无聊暑假!高中生必藏神器大公开

嘿&#xff0c;各位高中生朋友们&#xff0c;最近是不是被这没完没了的暴雨困在家里&#xff0c;感觉暑假生活都快发霉了&#xff1f;别急&#xff0c;今天我要揭秘一个宝藏网站—— ai123.cn&#xff0c;它简直就是咱们暑期宅家必备的救星&#xff01;接下来&#xff0c;我就来…

whaler_通过镜像导出dockerfile

1、Whaler简介 Whaler:从镜像导出Dockerfile&#xff0c;whaler英文释义捕鲸船。 2、下载安装 # wget -cO /usr/local/bin/whaler https://github.com/P3GLEG/Whaler/releases/download/1.0/Whaler_linux_amd64 3、赋予可执行权限 [rootlocalhost ~]# chmod x /usr/local/…

Web漏洞扫描工具(AWVS、Goby)

一、背景 想针对自己项目或者小公司的Web安全做相关扫描&#xff0c;自己做漏洞进行自查工作&#xff0c;能够减少自身系统的安全风险&#xff0c;提高系统的安全性。但是没有找到一些开源性质的、扫描质量比较高的相关工具&#xff0c;使用安全公司的专业产品价格又承受不起。…

每日一练,java06

这里写目录标题 题目1.局部变量能否和成员变量重名&#xff1f;2.下面哪个不属于HttpServletResponse接口完成的功能&#xff1f;3.以下代码结果是什么&#xff1f;4.实现或继承了Collection接口的是&#xff08;&#xff09;知识点局部变量与成员变量重名equals与HttpServletR…

5. 开发环境搭建

1. 概述 基于ubuntu20.04搭建开发环境 2. 开发环境安装 恒玄SDK编译&#xff0c;依赖gcc-arm的编译工具&#xff0c;编译工具由恒玄提供&#xff1b; 2.1 配置编译工具链的环境变量 修改~/.profile文件 source ~/.profile 2.2 安装依赖包 sudo apt install ccache sudo a…

一刷代码随想录(回溯4)

递增子序列 题意&#xff1a; 给定一个整型数组, 你的任务是找到所有该数组的递增子序列&#xff0c;递增子序列的长度至少是2。 示例: 输入: [4, 6, 7, 7]输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]] 说明: 给定数组的长度不会…

【最新】cuda和cudnn和显卡驱动的对应关系

NV官方文档Support Matrix — NVIDIA cuDNN v9.2.1 documentation下列的非常清楚&#xff0c;如图&#xff1a;

【SpringBoot】 4 Thymeleaf

官网 https://www.thymeleaf.org/ 介绍 Thymeleaf 是一个适用于 Web 和独立环境的现代服务器端 Java 模板引擎。 模板引擎&#xff1a;为了使用户界面和业务数据分离而产生的&#xff0c;它可以生成特定格式的文档&#xff0c;用于网站的模板引擎会生成一个标准的 html 文档…

捉虫笔记(1)之 WinDbg符号配置

WinDbg符号配置 1、WinDbg简单介绍 WinDbg 是微软的一款强大的调试工具&#xff0c;用于 Windows 平台的内核和用户模式调试。它提供了一系列强大的功能&#xff0c;包括内存和寄存器的查看、断点设置、堆栈跟踪、性能分析等。 WinDbg 的历史可以追溯到微软早期的调试工具&a…

[Unity] ShaderGraph实现不同贴图素材的同一材质球复用

无意间发现的ShaderGraph小技巧&#xff0c; 可以实现同一个ShaderGraph&#xff0c;同一个Material材质球&#xff0c; 但使用不同的Texture贴图&#xff0c;而Sprite显示不会相互覆盖。 具体实现方法如下&#xff1a; 声明Texture2D时&#xff0c;把名字命名成&#xff1a…

51单片机嵌入式开发:17、STC89C52的嵌入式 遥控器 控制步进电机 转速 和 转向 操作并 printf打印信息

51单片机嵌入式开发 STC89C52的嵌入式 遥控器 控制步进电机 转速 和 转向 操作并 printf打印信息 51单片机嵌入式开发STC89C52的嵌入式 遥控器 控制步进电机 转速 和 转向 操作并 printf打印信息1 概述2 硬件电路2.1 遥控器2.2 红外接收器电路2.3 STC89C52单片机电路2.4 数码管…

skynet热更新之inject

游戏服务器的热更新是一种常见的需求&#xff0c;skynet可以通过inject的方式&#xff0c;来修改一个服务的消息处理函数&#xff0c;达到热更新的效果。 skynet内置服务debug_console skynet自带了一个调试控制台服务。inject注入代码需要先启动这个服务。 skynet.newservi…

【python】python大学排名数据抓取+可视化(源码+数据集+可视化+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

uart开发调试

1. Uart基本框架 1.1概念 通信系统有两种方式&#xff0c;同步通信和异步通信. 同步通信的典型特征&#xff1a;通信双方公用同一个时钟&#xff0c;发送/接受速率完全一致&#xff0c;通信时需要带时钟信号传输. 异步通信的典型特征&#xff1a;通信双方各自具有独立的时钟…

MyBatis操作数据库 -- 动态SQL

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|Spring &#x1faf5; 与天斗其乐无穷 文章目录 1. 动态SQL<if>标签<trim>标签<where> 标签<set> 标签<foreach> 标签<include>标签注解方式 1. 动态SQL 动态sql能够实现不同条件下的sql拼接 …

jquery+bootstrap实现DOM转图片并下载

&#x1f34a;jquery实现DOM结构转图片并下载 版本介绍&#xff1a; Bootstrap v3.3.7jQuery v3.5.1domToImage.js 根据Bootstrap实现dialog上一步下一步多个弹窗交互进行大肆修改&#xff0c;完善了第二步生成图片的功能与更强的交互 1.、功能说明 重新设置bootstrap主题色 …

DNS应用以及扩展知识

&#xff08;一&#xff09;DNS正向代理 1.首先在DNS服务器上安装bind包&#xff0c;安装环境 此部分参考上一个笔记 2.修改配置文件 vim /etc/named.conf 在配置文件中加上"any;" 3.然后配置/etc/named.rfc1912.zonesw文件 添加选中部分 选中部分有一个file文…

24年第三届钉钉杯大学生大数据挑战赛浅析

需要完整资料&#xff0c;请关注WX&#xff1a;“小何数模”&#xff01; 本次钉钉杯大数据挑战赛的赛题已正式出炉&#xff0c;无论是赛题难度还是认可度&#xff0c;该比赛都是仅次于数模国赛的独一档&#xff0c;可以用于国赛前的练手训练。考虑到大家解题实属不易&#xf…