数据结构--链表

news/2024/9/19 5:18:20/ 标签: 数据结构, 链表

文章目录

链表

链表是一种常见的数据结构,由一系列节点构成,每个节点包含当前节点的数据和一个指针(单向链表)或者两个指针(双向链表),链表是一种动态的数据结构,可以动态的增删节点。

1.链表的特点

  • 逻辑结构:线性结构

  • 物理结构:不要求连续的存储空间

  • 存储特点:链表由一系列结点node(链表中每一个元素称为结点)组成,结点可以在代码执行过程中动态创建。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域

2.链表的基础操作

2.1增

增加结点的逻辑是:将新增结点的指针域指向后一个结点,然后将原链表中的前一个结点的指针域指向新增的结点。(注意顺序不能颠倒,否则会导致插入位置后面的结点全部丢失)

在这里插入图片描述

//头插法
public void addFirst(int data){Node node=new Node(data);node.next=this.head;this.head=node;
}//尾插法
public void addLast(int data){Node node=new Node(data);Node cur=this.head;if(this.head==null){addFirst(data);}else{while (cur.next!=null){cur=cur.next;}cur.next=node;}
}//给定位置插入
public boolean addIndex(int index,int data){Node node=new Node(data);Node cur=this.head;if(index==0){addFirst(data);return true;}else if(index==size()){addLast(data);return true;}if(index<0||index>size()){System.out.println("插入位置不合法");return false;}else{for (int i = 0; i <index-1 ; i++) {cur=cur.next;}//插入节点的尾指向下一个结点的头node.next=cur.next;//链表插入位置元素的下一个结点指向插入元素的头cur.next=node;}return true;
}

2.2删

//删除第一次出现关键字为key的节点    
public void remove(int key){Node cur=this.head;if(cur==null){System.out.println("链表为空,删除错误");return;}else if(cur.val==key&&cur.next==null){this.head=null;return;}else if(this.head.val!=key&&cur.next==null){System.out.println("未找到key");return;}else if(this.head.val==key){this.head=this.head.next;return;}while (cur.next!=null){if(cur.next.val==key){cur.next=cur.next.next;return;}cur=cur.next;}System.out.println("未找到key");
}
// 删除所有值为key的节点    
public void removeAllKey(int key){Node cur=this.head;if(cur==null){System.out.println("链表为空,删除错误");}else if(cur.next==null&&cur.val==key){this.head=null;}else if(cur.next==null&&this.head.val!=key){System.out.println("未找到key");}else if(cur.val==key){this.head=this.head.next;}while (cur.next!=null){if(cur.next.val==key){cur.next=cur.next.next;continue;}cur=cur.next;}
}

3.自定义链表

3.1 自定义单向链表

在这里插入图片描述

/*
单链表中的节点。
节点是单向链表中基本的单元。
每一个节点Node都有两个属性:一个属性:是存储的数据。另一个属性:是下一个节点的内存地址。*/
public class Node {// 存储的数据Object data;// 下一个节点的内存地址Node next;public Node(){}public Node(Object data, Node next){this.data = data;this.next = next;}
}
/*
链表类(单向链表)*/
public class Link<E> {// 头节点Node header;private int size = 0;public int size(){return size;}// 向链表中添加元素的方法(向末尾添加)public void add(E data){//public void add(Object data){// 创建一个新的节点对象// 让之前单链表的末尾节点next指向新节点对象。// 有可能这个元素是第一个,也可能是第二个,也可能是第三个。if(header == null){// 说明还没有节点。// new一个新的节点对象,作为头节点对象。// 这个时候的头节点既是一个头节点,又是一个末尾节点。header = new Node(data, null);}else {// 说明头不是空!// 头节点已经存在了!// 找出当前末尾节点,让当前末尾节点的next是新节点。Node currentLastNode = findLast(header);currentLastNode.next = new Node(data, null);}size++;}/*** 专门查找末尾节点的方法。*/private Node findLast(Node node) {if(node.next == null) {// 如果一个节点的next是null// 说明这个节点就是末尾节点。return node;}// 程序能够到这里说明:node不是末尾节点。return findLast(node.next); // 递归算法!}/*// 删除链表中某个数据的方法public void remove(Object obj){//略}// 修改链表中某个数据的方法public void modify(Object newObj){//略}// 查找链表中某个元素的方法。public int find(Object obj){//略}*/
}

3.2 自定义双向链表

在这里插入图片描述

/*
双向链表中的节点。*/
public class Node<E> {Node prev;E data;Node next;Node(Node prev, E data, Node next) {this.prev = prev;this.data = data;this.next = next;}
}
/*** 链表类(双向链表)* @author 尚硅谷-宋红康* @create 15:05*/
public class MyLinkedList<E> implements Iterable<E>{private Node first;  //链表的首元素private Node last;   //链表的尾元素private int total;public void add(E e){Node newNode = new Node(last, e, null);if(first == null){first = newNode;}else{last.next = newNode;}last = newNode;total++;}public int size(){return total;}public void delete(Object obj){Node find = findNode(obj);if(find != null){if(find.prev != null){find.prev.next = find.next;}else{first = find.next;}if(find.next != null){find.next.prev = find.prev;}else{last = find.prev;}find.prev = null;find.next = null;find.data = null;total--;}}private Node findNode(Object obj){Node node = first;Node find = null;if(obj == null){while(node != null){if(node.data == null){find = node;break;}node = node.next;}}else{while(node != null){if(obj.equals(node.data)){find = node;break;}node = node.next;}}return find;}public boolean contains(Object obj){return findNode(obj) != null;}public void update(E old, E value){Node find = findNode(old);if(find != null){find.data = value;}}@Overridepublic Iterator<E> iterator() {return new Itr();}private class Itr implements Iterator<E>{private Node<E> node = first;@Overridepublic boolean hasNext() {return node!=null;}@Overridepublic E next() {E value = node.data;node = node.next;return value;}}
}

自定义双链表测试:

package com.atguigu.list;public class MyLinkedListTest {public static void main(String[] args) {MyLinkedList<String> my = new MyLinkedList<>();my.add("hello");my.add("world");my.add(null);my.add(null);my.add("java");my.add("java");my.add("atguigu");System.out.println("一共有:" + my.size());System.out.println("所有元素:");for (String s : my) {System.out.println(s);}System.out.println("-------------------------------------");System.out.println("查找java,null,haha的结果:");System.out.println(my.contains("java"));System.out.println(my.contains(null));System.out.println(my.contains("haha"));System.out.println("-------------------------------------");System.out.println("替换java,null后:");my.update("java","JAVA");my.update(null,"songhk");System.out.println("所有元素:");for (String s : my) {System.out.println(s);}System.out.println("-------------------------------------");System.out.println("删除hello,JAVA,null,atguigu后:");my.delete("hello");my.delete("JAVA");my.delete(null);my.delete("atguigu");System.out.println("所有元素:");for (String s : my) {System.out.println(s);}}
}

http://www.ppmy.cn/news/1527532.html

相关文章

mysql怎样优化count(*) from 表名 where …… or ……这种慢sql

一 问题描述 线上发现一条类似这样的慢sql&#xff08;查询时长8s&#xff09;&#xff1a; select id,name,(select count(*) from t14 where t14.idt15.id or t14.id2t15.id) as cnt from t15 ; t14的id和id2字段上都有索引&#xff0c;但是因为条件里有or&#xff0c;导致…

21. 什么是MyBatis中的N+1问题?如何解决?

N1 问题是指在进行一对多查询时&#xff0c;应用程序首先执行一条查询语句获取结果集&#xff08;即 1&#xff09;&#xff0c;然后针对每一条结果&#xff0c;再执行 N 条额外的查询语句以获取关联数据。这个问题通常出现在 ORM 框架&#xff08;如 MyBatis 或 Hibernate&…

给虚拟机linux系统安装交叉编译工具链

我们在电脑上写的代码编译生成的是X86架构的二进制文件&#xff0c;只能在X86平台上运行&#xff0c;而开发板是ARM架构因此需要安装交叉编译链工具&#xff0c;这样在电脑上写的代码交叉编译之后生成的是ARM架构的二进制文件。 绿色的字眼是与本文无关的只是这样有助于我们的…

python 实现entropy熵算法

entropy熵算法介绍 Entropy&#xff08;熵&#xff09;算法并不是一个单一的、具体的算法&#xff0c;而是一个广泛的概念&#xff0c;用于描述系统无序程度或信息不确定性的量度。在计算机科学、信息论、热力学等多个领域中&#xff0c;熵都有重要的应用。 在计算机科学中&a…

【Vue】- 生命周期和数据请求案例分析

文章目录 知识回顾前言源码分析1. 生命周期2. 请求数据案例分析 拓展知识 总结 知识回顾 前言 Vue生命周期 ● 就是一个Vue实例从创建 到 销毁 的整个过程。 生命周期四个阶段&#xff1a;① 创建 ② 挂载 ③ 更新 ④ 销毁 ● 创建阶段&#xff1a;创建响应式数据 ● 挂载阶段…

【七篇文章从零速通transformer】01 从零开始解密神经网络:深度学习基础全解析

文章简介 本系列文章旨在帮助零基础的读者系统地掌握深度学习,最终能够理解 Transformer 架构。本篇文章是第一篇,我们将从深度学习最核心的知识——神经网络——开始讲解,深入浅出地带你了解神经网络的结构、如何让神经网络工作,激活函数、损失函数、优化器和反向传播等关…

Router安装以及导入

安装 本文适合Vue3的项目使用 安装vue-router4 npm install vue-router4在src目录下创建router的文件夹&#xff0c;并新建一个index.js在index.js中导入vue-router&#xff0c;并定义其实例 import { createRouter, createWebHistory } from vue-router//在其中定义路由 c…

[网络]TCP/IP协议 之 TCP协议的核心机制(2)

文章目录 TCP核心机制1. 确认应答2. 超时重传3. 连接管理三次握手四次挥手 4. 滑动窗口5. 流量控制6. 拥塞控制7. 延时应答8. 捎带应答9. 粘包问题10. 异常情况 TCP核心机制 1. 确认应答 (上篇) 2. 超时重传 (上篇) 3. 连接管理 建立连接的流程: 三次握手 断开连接的流程…

3本SCI/SSCI期刊更名,9月WOS更新!速看!

SCI/SSCI期刊目录9月份已更新&#xff01;快来查收最新动态&#xff01;如有相关领域作者有意投稿&#xff0c;可作为重点关注&#xff01; ​ 期刊动态 2024年9月科睿唯安期刊目录更新 2024年9月18日&#xff0c;科睿唯安更新了WOS期刊目录&#xff0c;此次更新&#xff0c…

OceanBase 运维管理工具 OCP 4.x 升级:聚焦高可用、易用性及可观测性

可视化的管控平台&#xff0c;对 OceanBase 这类的分布式数据库及大规模数据的运维管理来说&#xff0c;是提升运维效率与数据库管理水平的重要工具。OceanBase 运维管理工具 OCP 作为专为OceanBase数据库设计的企业级全生命周期管理平台&#xff0c;为用户提供了全面的数据库可…

RocketMQ出现The broker does not support consumer to filter message by SQL92

在使用RocketMQ使用SQL过滤消息的时候&#xff0c;出现下面错误 原因是我们的配置文件没有开启SQL过滤功能&#xff0c;我们需要在每个配置文件中添加下面命令 #开启过滤消息时支持SQL92标准 enablePropertyFiltertrue接着我们重启namesrv与broker服务就解决问题 # 1.进入bi…

matlab边缘点提取函数

1、边缘提取 matlab自带点云边缘提取函数,用于搜索点云边界,其核心是alpha shapes算法。alpha shapes提取边缘点,主要是依据滚动圆绕点云进行旋转,实现边缘检测,原理如下图所示。具体原理及效果,可以参考之前我写的博客:基于alpha shapes的边缘点提取(matlab)-CSDN博客…

QT之QML从入门到精通(第三章)

QML-Property 关于属性的设置 MyRectangle.qml import QtQuick 2.12 import QtQuick.Window 2.12 //2.15 import QtQuick.Controls 2.12 //可以引入别的控件 import Qt.labs.folderlistmodel 2.12 import Qt.labs.platform 1.0 as PlatformRectangle {id:borderRectrequired…

【FastAPI】实现服务器向客户端发送SSE(Server-Sent Events)广播

在FastAPI中实现服务器向客户端发送SSE&#xff08;Server-Sent Events&#xff09;广播&#xff0c;可以通过以下步骤实现。SSE是一种服务器推送技术&#xff0c;允许服务器发送实时数据到客户端&#xff0c;通常用于创建实时更新的应用程序。 1. 安装必要的依赖 首先&#…

python函数一:函数的概念、函数定义与调用、函数的参数、函数的返回值、说明文档以及函数的嵌套调用

文章目录 1. 函数介绍1.1 函数的概念1.2 函数定义与调用1.2 函数的参数1.3 函数的返回值1.4 说明文档 2. 函数的嵌套调用2.1 嵌套调用及执行流程2.2 嵌套调用的应用 1. 函数介绍 1.1 函数的概念 什么是函数&#xff1f; 函数:是一个被命名的、独立的、完成特定功能的代码段&am…

【爬虫软件】批量采集抖音主页已发布作品

一、背景介绍 以下xx代表你猜中的部分。 1.1 爬取目标 用python开发的xx爬虫采集软件&#xff0c;可自动按博主抓取其已发布视频。 为什么有了源码还开发界面软件呢&#xff1f;方便不懂编程代码的小白用户使用&#xff0c;无需安装python&#xff0c;无需改代码&#xff0c;…

el-input设置type=‘number‘和v-model.number的区别

el-input设置typenumber’与设置.number修饰符的区别 1. 设置type‘number’ 使用el-input时想收集数字类型的数据&#xff0c;我们首先会想到typenumber&#xff0c;设置完type为number时会限制我们输入的内容只能为数字&#xff0c;不能为字符/汉字等非数字类型的数值&…

大数据处理技术:分布式文件系统HDFS

目录 1 实验名称&#xff1a; 2 实验目的 3 实验内容 4 实验原理 5 实验过程或源代码 5.1 HDFS的基本操作 5.2 HDFS-JAVA接口之读取文件 5.3 HDFS-JAVA接口之上传文件 5.4 HDFS-JAVA接口之删除文件 6 实验结果 6.1 HDFS的基本操作 6.2 HDFS-JAVA接口之读取文件 6.…

php变量赋值javascipt变量

javascript变量可以通过document.getElementById()获取html变量值php变量 可以在不同php脚本中使用&#xff0c;最后一次使用变量的初始值位为上一次使用变量的值 <!DOCTYPE html> <html> <body><?php $a "Hello World!"; echo $a; ?> …

Java入门程序-HelloWorld

Java程序开发的三个步骤 1.编写代码得到 .java 源代码文件 2.使用javac编译得到 .class 字节码文件 3.使用java运行 注意事项 建议代码文件名全英文&#xff0c;首字母大写&#xff0c;满足驼峰命名法&#xff0c;源代码文件的后缀必须是.java 开发HelloWorld程序 &…