(顺序表、单链表、双链表)==>一篇解决!(Java版)
文章目录
- 一、线性表
- 二、顺序表
- 三、单链表
- 四、双链表
一、线性表
线性表是最基本、最简单、也是最常用的一种数据结构。一个线性表是n个具有相同特性的数据元素的有限序列。
线性表的特征:数据元素之间具有一种“一对一”的逻辑关系。
线性表的分类:
线性表中数据存储的方式有两种:顺序存储和链式存储,按照数据的存储方式不同,可以把线性表分为顺序表和链表,链表又有单链表和双链表两种。
二、顺序表
顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元,依次存储线性表中的各个元素、使得线性表中再逻辑结构上响铃的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。
如图:
我们用代码实现顺序表,我们应要考虑到成员变量、构造方法、成员方法。
一.成员变量:
我们使用数组来实现顺序表,其成员变量就是要有两个,一个是存储元素的数组,一个是记录当前顺序表有效的长度.
二.构造方法:
创建一个有参的构造方法,来初始化数组的容量和其有效长度
三.成员方法:
1.public void clear():清空顺序表
2.publicboolean isEmpty():判断表是否为空,是返回true,否返回false
3.public int length():获取表中元素的个数
4.public T get(int i):获取表中的第i个元素
5.public void insert(int i,T t):在表的第i个元素之前插入一个值为t的数据元素。
6.public void insert(T t):向表中添加一个元素t(尾插)
7.public T remove(int i):删除表中第i个元素。
8.public int indexOf(T t):返回表中首次出行元素t时的下标。
9.public void resize(int newSize): 当数组满了,根据newSize进行扩容。
10.顺序表的遍历,就要实现Iterable接口
接下来就是代码实现:
具体思路都在代码注释中
import java.util.Iterator;public class SequenceList <T> implements Iterable<T>{//存储元素的数组private T[] eles;//顺序表的长度private int N;//构造方法.创建容量为capacity的SequenceList对象public SequenceList(int capacity) {this.eles = (T[]) new Object[capacity];//这里表示的是有效元素数据this.N = 0;}//空置顺序表public void clear() {this.N = 0;}//判断顺序表是否为空,是返回true,反之返回falsepublic boolean isEmpty() {return N == 0;}//获取顺序表中的元素个数public int length() {return N;}//读取并返回顺序表中的第i个元素的值public T get(int i) {return eles[i];}//在第i个元素之前插入一个值为t的数据元素public void insert(int i, T t) {//先判断容量是否足够if (N == eles.length) {//不够则扩容,一般是原数组长度的两倍resize(2 * N);}//需要吧i位置元素向后移动一位即可for (int index = N; index >= i; index--) {eles[index] = eles[index - 1];}//然后把t元素放进来eles[i] = t;//有效元素+1N++;}//向线性表中添加一个元素tpublic void insert(T t) {//先判断容量是否足够if (N == eles.length) {//不够则扩容,一般是原数组长度的两倍resize(2 * N);}eles[N++] = t;}//扩容根据newSize,重置eles的大小public void resize(int newSize) {//定义一个辅助数组,备份elesT[] arr = eles;//创建新数组eles = (T[]) new Object[newSize];//把原数组的值复制过去for (int i = 0; i < N; i++) {eles[i] = arr[i];}}//删除并返回线性表中第i个数据元素public T remove(int i) {//先记录i索引处的值T temp = eles[i];//将i数据后面的数据向前覆盖for (int index = i; index <= N; index++) {eles[i] = eles[i + 1];}//减少有效长度N--;//如果有效长度小于数组长度的四分之一,就要缩值,缩小二分之一if (N < eles.length / 4) {resize(eles.length / 2);}return temp;}//查找t元素第一次出现的位置,没有则返回-1public int indexOf(T t) {//遍历顺序表,依次比对for (int i = 0; i < N; i++) {if (eles[i].equals(t))return i;}return -1;}//打印遍历顺序表
//重写iterator方法@Overridepublic Iterator iterator() {return new SIterator();}//构架一个内部类来实现Iterator接口private class SIterator implements Iterator{private int cur;public SIterator(){this.cur=0;}//是否还有下一个元素@Overridepublic boolean hasNext() {return cur<N;}//下一个元素@Overridepublic T next() {return eles[cur++];}}}
测试一下我们实现的顺序表的功能:
三、单链表
链表是一种物理存储单元上非连续、非顺序的存储结构,其物理结构不能只管的表示数据元素的逻辑顺序,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列的结点(链表中的每一个元素称为结点)组成,结点可以在运行时动态生成。
链表顾名思义我们可以想象一下链子的样子,每一段就是一个节点,没有固定形状比较灵活,我们上图看一下:
像这样每个节点相连接.
我们把它具体的实现一下,更容易理解:
每个节点都是单独的个体,我们可以将其连接起来变为链表,我们先来定义一下节点类:
private class Node {//存储数据T data;//下一个节点Node next;//构造节点public Node(T data, Node next) {this.data = data;this.next = next;}
接着我们还是要对其进行设计:
一、成员变量:
1.private Node head:记录首结点
2.private int N:记录链表的长度
二、构造方法:
LinkList():创建LinkList对象
三、成员方法:
1.public void clear():空置链表
2.publicboolean isEmpty():判断表是否为空,是返回true,否返回false
3.public int length():获取表中元素的个数
4.public T get(int i):读取并返回表中的第i个元素的值
5.public void insert(T t):往表中添加一个元素;
6.public void insert(int i,T t):在表的第i个元素之前插入一个值为t的数据元素。
7.public T remove(int i):删除并返回表中第i个数据元素。
8.public int indexOf(T t):返回表中首次t数据元素的位序号,若不存在,则返回-1
9.链表遍历=>实现Iterator接口
代码实现:
import java.util.Iterator;public class LinkList<T> implements Iterable<T>{//记录首节点private Node head;//记录链表的长度private int N;//节点类private class Node {//存储数据T data;//下一个节点Node next;//构造节点public Node(T data, Node next) {this.data = data;this.next = next;}}public LinkList() {//初始化头结点this.head = new Node(null, null);//初始化元素个数this.N = 0;}//空置链表public void clear() {head.next = null;N = 0;}//判断链表表是否为空public boolean isEmpty() {return N == 0;}//获取元素个数public int length() {return N;}//获取i位置的元素public T get(int i) {//安全检查if (i < 0 || i >= N) {throw new RuntimeException("位置不合法!");}//遍历链表即可Node n = head.next;for (int index = 0; index < i; index++) {n = n.next;}return n.data;}//添加元素(尾插法)public void insert(T t){Node n = head;//循环至尾节点while(n.next != null) {n = n.next;}//此时就是尾节点了,直接插入//构建值为t的节点Node newNode = new Node(t, null);n.next = newNode;//有效长度+1N++;}//在i位置,插入一个值为t的数据元素//1.找到i位置的前一个节点//2.使i-1位置的节点指向新节点,新节点在指向原本i位置的节点即可public void insert(int i, T t) {//安全检查if (i < 0 || i > N){throw new RuntimeException("位置不合法!");}//查找到i - 1位置的节点Node n = head;for (int index = 0; index <= i - 1; i++) {n = n.next;}//创建新节点Node newNode = new Node(t, null);//保留原本i位置处的节点Node cur = n.next;//i - 1位置的节点指向新节点n.next = newNode;//新节点指向原本i位置的节点newNode.next = cur;//有效长度+1N++;}//删除第i个数据元素//将第i - 1位置的元素,指向i + 1位置的节点即可public T remove(int i) {//安全检查if (i < 0 || i >= N){throw new RuntimeException("位置不合法");}//找到第i - 1位置的元素Node n = head;for (int index = 0; index <= i - 1; index++) {n = n.next;}//记录i位置节点的值Node cur = n.next;//i - 1位置的节点指向i + 1位置的节点n.next = cur.next;//有效长度-1N--;//返回被删除的值return cur.data;}//t元素数据首先出现时的位序号,没找到返回-1public int indexOf(T t) {//遍历查找Node n = head;for (int i = 0; i < N; i++) {n = n.next;if (n.data.equals(t)) {return i;}}return -1;}//重写Iterator接口方法@Overridepublic Iterator<T> iterator() {return new LIterator();}//定义内部类,实现遍历private class LIterator implements Iterator<T> {private Node n;public LIterator() {this.n = head;}@Overridepublic boolean hasNext() {return n.next != null;}@Overridepublic T next() {n = n.next;return n.data;}}
}
测试一下:
四、双链表
双向链表也叫双向表,是链表的一种,它由多个结点组成,每个结点都由一个数据域和两个指针域组成,数据域用来存储数据,其中一个指针域用来指向其后继结点,另一个指针域用来指向前驱结点。链表的头结点的数据域不存储数据,指向前驱结点的指针域值为null,指向后继结点的指针域指向第一个真正存储数据的结点。
如图:
接下来我们实现一下双链表:
一、成员变量:
1.private Node first:首结点
2.private Node last:尾节点
2.private int N:记录链表的长度
二、构造方法:
TowWayLinklist():创建TowWayLinklist对象
三、成员方法:
1.public void clear():空置链表
2.publicboolean isEmpty():判断表是否为空,是返回true,否返回false
3.public int length():获取表中元素的个数
4.public T get(int i):读取并返回表中的第i个元素的值
5.public void insert(T t):往表中添加一个元素;
6.public void insert(int i,T t):在表的第i个元素之前插入一个值为t的数据元素。
7.public T remove(int i):删除并返回表中第i个数据元素。
8.public int indexOf(T t):返回表中首次t数据元素的位序号,若不存在,则返回-1
9.public T getFirst():获取第一个元素
10.public T getLast():获取最后一个元素
9.链表遍历=>实现Iterator接口
代码实现:
import java.util.Iterator;public class TowWayLinklist<T> implements Iterable<T> {//首结点private Node head;//最后一个结点private Node last;//链表的长度private int N;//结点类private class Node{public Node(T item, Node pre, Node next) {this.item = item;this.pre = pre;this.next = next;}//存储数据public T item;//指向上一个结点public Node pre;//指向下一个结点public Node next;}public TowWayLinklist() {//初始化头结点和尾结点this.head = new Node(null,null,null);this.last=null;//初始化元素个数this.N=0;}//清空链表public void clear(){this.head.next=null;this.head.pre=null;this.head.item=null;this.last=null;this.N=0;}//获取链表长度public int length(){return N;}//判断链表是否为空public boolean isEmpty(){return N==0;}//获取第一个元素public T getFirst(){if (isEmpty()){return null;}return head.next.item;}//获取最后一个元素public T getLast(){if (isEmpty()){return null;}return last.item;}//插入元素tpublic void insert(T t){if (isEmpty()){//如果链表为空://创建新的结点Node newNode = new Node(t,head, null);//让新结点称为尾结点last=newNode;//让头结点指向尾结点head.next=last;}else {//如果链表不为空Node oldLast = last;//创建新的结点Node newNode = new Node(t, oldLast, null);//让当前的尾结点指向新结点oldLast.next=newNode;//让新结点称为尾结点last = newNode;}//元素个数+1N++;}//向指定位置i处插入元素tpublic void insert(int i,T t){//找到i位置的前一个结点Node pre = head;for(int index=0;index<i;index++){pre=pre.next;}//找到i位置的结点Node curr = pre.next;//创建新结点Node newNode = new Node(t, pre, curr);//让i位置的前一个结点的下一个结点变为新结点pre.next=newNode;//让i位置的前一个结点变为新结点curr.pre=newNode;//元素个数+1N++;}//获取指定位置i处的元素public T get(int i){Node n = head.next;for(int index=0;index<i;index++){n=n.next;}return n.item;}//找到元素t在链表中第一次出现的位置public int indexOf(T t){Node n = head;for(int i=0;n.next!=null;i++){n=n.next;if (n.next.equals(t)){return i;}}return -1;}//删除位置i处的元素,并返回该元素public T remove(int i){//找到i位置的前一个结点Node pre = head;for(int index=0;index<i;index++){pre=pre.next;}//找到i位置的结点Node curr = pre.next;//找到i位置的下一个结点Node nextNode= curr.next;//让i位置的前一个结点的下一个结点变为i位置的下一个结点pre.next=nextNode;//让i位置的下一个结点的上一个结点变为i位置的前一个结点nextNode.pre=pre;//元素的个数-1N--;return curr.item;}@Overridepublic Iterator<T> iterator() {return new TIterator();}private class TIterator implements Iterator{private Node n;public TIterator(){this.n=head;}@Overridepublic boolean hasNext() {return n.next!=null;}@Overridepublic Object next() {n=n.next;return n.item;}}}
测试一下:
相关文章:

(顺序表、单链表、双链表)==>一篇解决!(Java版)
文章目录 一、线性表二、顺序表三、单链表四、双链表 一、线性表 线性表是最基本、最简单、也是最常用的一种数据结构。一个线性表是n个具有相同特性的数据元素的有限序列。 线性表的特征:数据元素之间具有一种“一对一”的逻辑关系。 线性表的分类: 线…...

JPG与PDF格式转换器
该插件可实现JPG与PDF格式的互转。 MainForm.Designer.cs using System.Windows.Forms; namespace JpgToPdfConverter {partial class MainForm{private System.ComponentModel.IContainer components null;protected override void Dispose(bool disposing){if (disposing &…...
如何在 CentOS 7 虚拟机上配置静态 IP 地址并保持重启后 SSH 连接
在使用 CentOS 7 的虚拟机时,我们通常需要配置静态 IP 地址,以确保在每次虚拟机重启后能够通过 SSH 连接。本文将介绍如何在 CentOS 7 系统中配置静态 IP 地址,并确保配置在系统重启后依然生效。 步骤 1:检查虚拟机网络接口 首先…...

手搓传染病模型(SEIARW)
在传染病传播的研究中,水传播途径是一个重要的考量因素。SEAIRW 模型(易感者 S - 暴露者 E - 感染者 I - 无症状感染者 A - 康复者 R - 水中病原体 W)综合考虑了人与人接触传播以及水传播的双重机制,为分析此类传染病提供了全面的…...

【Mac 从 0 到 1 保姆级配置教程 15】- Python 环境一键安装与配置,就是这么的丝滑
文章目录 前言安装 Python 环境VSCode 配置Python 环境NeoVim 配置 Python 环境(选看)1. Python LSP 配置2. 打开 python 语言支持 最后参考资料系列教程 Mac 从 0 到 1 保姆级配置教程目录,点击即可跳转对应文章: 【Mac 从 0 到 …...

【递归、搜索与回溯】专题一:递归(二)
📝前言说明: 本专栏主要记录本人递归,搜索与回溯算法的学习以及LeetCode刷题记录,按专题划分每题主要记录:(1)本人解法 本人屎山代码;(2)优质解法 优质代码…...

Spark缓存-cache
一、RDD持久化 1.什么时候该使用持久化(缓存) 2. RDD cache & persist 缓存 3. RDD CheckPoint 检查点 4. cache & persist & checkpoint 的特点和区别 特点 区别 二、cache & persist 的持久化级别及策略选择 Spark的几种持久化…...

记录算法笔记(2025.5.13)二叉树的最大深度
给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:3 示例 2: 输入:root [1,null,2] …...

【Linux】简单设计libc库
📝前言: 经过之间两篇文章,【Linux】基础IO(一)和【Linux】基础IO(二)的学些,我们对文件的基础IO已经有了一定的理解。 这篇文章我们来简单设计一下libc库,来复习一下文…...

milvus+flask山寨《从零构建向量数据库》第7章case2
继续流水账完这本书,这个案例是打造文字形式的个人知识库雏形。 create_context_db: # Milvus Setup Arguments COLLECTION_NAME text_content_search DIMENSION 2048 MILVUS_HOST "localhost" MILVUS_PORT "19530"# Inference Arguments…...
岩土拉压试验机
岩土拉压试验机,专门用于检测黄土的在压缩、拉伸状态下的力学特性试验。主要由试验机主机、控制系统、控制软件三部分部分组成。 主要技术参数、配置如下: 主 要 技 术 指 标 及 参 数 最大试验力(kN) 5 试验精度等级 0.5级 …...
.Net HttpClient 使用准则
HttpClient 使用准则 System.Net.Http.HttpClient 类用于发送 HTTP 请求以及从 URI 所标识的资源接收 HTTP 响应。 HttpClient 实例是应用于该实例执行的所有请求的设置集合,每个实例使用自身的连接池,该池将其请求与其他请求隔离开来。 从 .NET Core …...

【Canda】常用命令+虚拟环境创建到选择
目录 一、conda常用命令 二、conda 环境 2.1 创建虚拟环境 2.2 conda环境切换 2.3 查看conda环境 2.4 删除某个conda环境 2.5 克隆环境 三、依赖包管理 3.1 安装命令 3.2 更新包 3.3 卸载包 3.4 查看环境中所有包 3.5 查看某个包的版本信息 3.6 搜索包 四、环境…...
Lighthouse Core Web Vitals 指标详解与优化指南
vLighthouse Core Web Vitals 指标详解与优化指南 一、Core Web Vitals 概述 Google 在 2020 年推出的 Core Web Vitals(核心网页指标)是衡量用户体验质量的关键指标集合,现已成为搜索引擎排名的重要因素。Lighthouse 作为 Google 官方的网页质量评估工具,提供了对这些指…...
Qt进阶开发:QTcpServer的详解
文章目录 一、QTcpServer 简介二、常用成员函数的使用三、信号函数的使用四、虚函数的使用五、连接多客户端-服务端示例一、QTcpServer 简介 QTcpServer 是 Qt 网络模块中的一个核心类,用于实现 基于 TCP 协议的服务端(Server),它负责监听端口、接收客户端连接请求,并通过…...
Leetcode 3544. Subtree Inversion Sum
Leetcode 3544. Subtree Inversion Sum 1. 解题思路2. 代码实现 题目链接:3544. Subtree Inversion Sum 1. 解题思路 这一题我的思路上就是一个动态规划的思路,因为原则上我们只需要遍历一下所有的状态即可,但是这样显然时间复杂度过高&am…...
物理:由基本粒子组成的个体能否提炼和重组?
个体差异源于基本粒子组合的复杂性与随机性,这一假设若成立,确实可能为生物医学带来革命性突破——但需要突破技术、理论与系统层级的多重壁垒。以下从科学逻辑与技术路径展开分析: 一、随机组合中的共性与稳定结构 1. 自然界的自组织规律 涌现性(Emergence):尽管粒子组…...
信息学奥赛一本通 1535:【例 1】数列操作
【题目链接】 ybt 1535:【例 1】数列操作 【题目考点】 1. 树状数组 【解题思路】 本题为树状数组模板题,维护区间和,进行单点修改,区间查询。 详细讲解见:洛谷 P3374 【模板】树状数组 1(树状数组解法…...

【登录认证】JWT令牌
一、概述 JWT全称:**JSON Web Token **(https://jwt.io/)定义了一种简洁的、自包含的格式,用于通信双方以json数据格式安全的传输信息。组成: ①第一部分:Header(头),记录令牌类型、签名算法等。例如: (“alg”:" HS256"," type":“…...
手撕算法(定制整理版2)
最长无重复子字符串 class Solution(object):def lengthOfLongestSubstring(self, s):""":type s: str:rtype: int"""if not s:return 0max_len 0tp []for a in s:while a in tp:del tp[0]tp.append(a)if len(tp) > max_len:max_len len(…...

python3:文件与异常
本来这篇教程是打算在base python数据类型之后出的,但是计划赶不上变化,反正最后都要融会贯通,今日有时间、今天遇到了类似的问题,就今天做这一模块的整理,顺序不是重点。 参考我的上一篇博客:https://blo…...

【兽医电子处方软件】佳易王宠物医院电子处方管理系统:宠物医院诊所用什么软件?一键导入配方模板软件程序实操教程 #操作简单 #宠物医院软件下载安装
一、概述 软件试用版资源文件下载方法: 【进入头像主页第一篇文章最后 卡片按钮 可点击了解详细资料 或左上角本博客主页 右侧按钮了解具体资料信息】 本实例以 佳易王宠物医院电子处方管理系统软件 为例说明,其他版本可参考本实例。试用版软…...
centos7.x下,使用宝塔进行主从复制的原理和实践
操作原理: 一、主库配置 1.修改 MySQL 配置文件 # 编辑主库配置文件(路径根据实际系统可能不同) vim /etc/my.cnf # 添加以下配置 [mysqld] server-id 1 # 唯一 ID,主库设置为 1 log-bin mysql-bin …...
langchain学习
无门槛免费申请OpenAI ChatGPT API搭建自己的ChatGPT聊天工具 https://nuowa.net/872 基本概念 LangChain 能解决大模型的两个痛点,包括模型接口复杂、输入长度受限离不开自己精心设计的模块。根据LangChain 的最新文档,目前在 LangChain 中一共有六大…...
从“听不懂”到“能对话”,声网AI让语音交互不再难用
人们谁懂啊!做智能客服系统的真的被传统语音机器整怕了!以前那些基于规则的 IVR 系统,“卡顿感” 拉满还总答非所问,用户说啥都像在对牛弹琴。不能打断、没有上下文、流程死板到离谱,动不动就来句 “请再说一遍”&…...
VSCode设置SSH免密登录
引言 2025年05月13日20:21:14 原来一直用的PyCharn来完成代码在远程服务器上的运行,但是PyCharm时不时同步代码会有问题。因此,尝试用VSCode来完成代码SSH远程运行。由于VSCode每次进行SSH连接的时候都要手动输入密码,为了解决这个问题在本…...
Windows Java gRPC 示例
gRPC是一个开源高性能远程过程调用(RPC)框架,因为这个框架最早是由Goolge开发的,这里的g 代表的也即是Google。 关于gRPC更多的概念介绍可以参考: gRPC 基本介绍 本篇快速介绍在Windows环境下使用 Java 语言如何实现 gRPC 的服务端和客户端调用。 1. 环境准备 JDK 21Ma…...

问题及解决02-处理后的图像在坐标轴外显示
一、问题 在使用matlab的appdesigner工具来设计界面,可以通过点击处理按钮来处理图像,并将处理后的图像显示在坐标轴上,但是图像超出了指定的坐标轴,即处理后的图像在坐标轴外显示。 问题图如下图所示。 原来的坐标轴如下图所…...

EasyX开发——绘制跟随鼠标移动的小球
游戏主循环: #include<graphics.h>int main() {initgraph(1280, 720);while (true){}return 0; } peekmessage函数:如果成功拉取到了消息,函数就会返回true,反之就会返回false 使用另外一个循环来不断地从消息队列当中拉取…...

【Qt开发】信号与槽
目录 1,信号与槽的介绍 2,信号与槽的运用 3,自定义信号 1,信号与槽的介绍 在Qt框架中,信号与槽机制是一种用于对象间通信的强大工具。它是在Qt中实现事件处理和回调函数的主要方法。 信号:窗口中&#x…...