Java数据结构-顺序表

目录

  • 1. 顺序表的相关概念
  • 1.1 线性表
  • 1.2 顺序表
  • 2. 功能实现
    • 2.1 整体框架
    • 2.2 乱七八糟的功能(bushi)
      • 2.2.1 判断容量是否满
      • 2.2.2 返回顺序表当前长度
      • 2.2.3 扩容
      • 2.2.4 清空整个顺序表
    • 2.3 插入数据
      • 2.3.1 头插数据
      • 2.3.2 尾插数据
      • 2.3.3 指定位置插入
    • 2.4 删除数据
      • 2.4.1 删除第一次出现的key
      • 2.4.2 删除所有的的key
    • 2.5 查找数据
      • 2.5.1 判定是否包含某个元素
      • 2.5.2 查找某个元素对应的位置
      • 2.5.3 pos位置不合法异常
      • 2.5.4 获取pos位置的元素:
    • 2.6 修改数据
  • 3. 全部代码

1. 顺序表的相关概念

1.1 线性表

线性表是一种常见的数据结构,它的特点是逻辑上是连续的线性结构,物理上不一定连续,常见的线性表有顺序表、链表、栈、队列……

1.2 顺序表

顺序表是线性表的一种,顺序表一般使用一段连续的地址来存储数据,比如数组。在数组中进行增删查改等操作。

2. 功能实现

顺序表分为静态顺序表(容量有限)和动态顺序表(可扩容),今天我们实现的是动态顺序表,并且能存储任意类型的数据,所以使用到了泛型的知识点,如果不了解泛型的小伙伴可以参考博主之前出的预备知识:
泛型初识

2.1 整体框架

一个顺序表中需要有:数组(用于存放有效数据)、容量、当前数据个数,所以我们定义一个类,成员变量分别是存放数据的数组array、记录当前数据个数的curSize、当前顺序表的容量Capacity(默认是10,可以按需修改)。在构造方法中初始化数组的内容,这样当我们实例化一个顺序表对象后,就能初始化顺序表了。

public class SeqList<T> {public Object[] array;//存放数据的数组public int curSize;//当前数据个数private int Capacity = 10;//容量public SeqList() {this.array = new Object[this.Capacity];}
}

2.2 乱七八糟的功能(bushi)

2.2.1 判断容量是否满

逻辑很简单,只要判断当前数据个数的curSize是否与顺序表的容量Capacity相等即可,如果满了返回true,没满返回false

    public boolean isFull() {return this.curSize == this.Capacity;}

2.2.2 返回顺序表当前长度

顺序表当前长度指的是当前数据的个数,直接将curSize返回即可

    //返回当前长度public int size() {return curSize;}

2.2.3 扩容

Arrays.copyOf方法能够实现数组的扩容并且将原有的数据拷贝。这里我们将容量扩大两倍,扩容之后别忘了将数组的容量Capacity也变为两倍

    //扩容private void dilatation() {this.array = Arrays.copyOf(this.array, 2 * this.Capacity);this.Capacity *= 2;}

2.2.4 清空整个顺序表

循环遍历顺序表,将每个元素依次置为null,然后将curSize和Capacity置为0

    //清空public void clear() {for (int i = 0; i < curSize; i++) {array[i] = null;}this.curSize = 0;this.Capacity = 0;}

2.3 插入数据

插入数据的方式有头插、尾插、在指定位置插入。一般情况下插入数据是尾插,所以我们把尾插和在指定位置插入这两个方法重载,头插方法另外实现一个。

2.3.1 头插数据

注意几个细节:
1.插入前判断容量够不够,如果不够需要扩容
2.如果顺序表中没有元素,直接添加,将数据赋值给0下标位置的元素
3.添加之后将当前数据个数curSize加1

如果顺序表中有数据且容量足够,插入前需将数据整体往后挪动,给第一个空出位置,如图:假设顺序表中有12、23、34、45这四个数据,头插法插入数据99
在这里插入图片描述

    //头插public void addFront(T data) {//如果满了,扩容if (isFull()) {dilatation();}//如果没有元素,直接添加if (this.curSize == 0) {this.array[0] = data;this.curSize++;return;}//开始添加int cur = curSize;while (cur > 0) {array[cur] = array[cur - 1];cur--;}array[0] = data;this.curSize++;}

2.3.2 尾插数据

插入数据前先判断容量够不够,如果不够,扩容。插入时,直接将curSize下标赋值为插入的数据即可

    //尾插public void add(T data) {if (isFull()) {//如果满了,扩容dilatation();}this.array[curSize] = data;this.curSize++;}

2.3.3 指定位置插入

指定位置插入,指的是pos位置插入数据

注意几个细节:
1.需要判断pos位置的合法性pos不能小于0,pos不能大于curSize(因为顺序表中的数据是连续的)
2.需要判断容量是否足够,如果不够需要扩容

    //在pos位置添加数据public void add(int pos, T data) throws PosNotLegalException {//判断pos位置合不合法try {if (pos < 0 || pos > this.curSize) {throw new PosNotLegalException("pos位置不合法");}} catch (PosNotLegalException e) {e.printStackTrace();}//如果满了,扩容if (isFull()) {dilatation();}//开始添加int cur = curSize;while (cur > pos) {array[cur] = array[cur - 1];cur--;}array[pos] = data;this.curSize++;}

2.4 删除数据

删除顺序表中的某个值key,分为两种,第一种是只删除第一次出现的key,第二种是删除所有的key

2.4.1 删除第一次出现的key

如果遇到了key,将key后面的元素整体往前挪动即可,让后一个位置的值覆盖前一个位置的值

    //移除第一次出现的keypublic void remove(T key) {int cur = -1;for (int i = 0; i < curSize; i++) {if (key.equals(array[i])) {cur = i;//记录该位置}}if (cur == -1) {System.out.println("找不到该元素");} else {//挪数据while (cur < curSize - 1) {array[cur] = array[cur + 1];cur++;}this.curSize--;}}

2.4.2 删除所有的的key

利用双指针算法移除所有的key,例如:在原数组(0,1,2 ,2 ,3, 0, 4 , 2)中移除所有的2。定义一个fast变量和slow变量,如果fast下标的值不等于要删除的值,则将fast下标的值赋值给fast下标;如果fast下标的值等于要删除的值,说明这个值不是我们需要的,这时让fast一个人往前走即可
核心代码:

if(arr[fast]!=key) {arr[slow]=arr[fast];fast++;slow++;
} else {fast++;
}

在这里插入图片描述

    //移除所有的keypublic void removeAll(T key) {//将所有的key都删除int fast = 0;int slow = 0;while (fast < this.curSize) {if (this.array[fast] != key) {array[slow] = array[fast];fast++;slow++;} else {fast++;}}this.curSize = slow;}

2.5 查找数据

2.5.1 判定是否包含某个元素

循环遍历顺序表所有元素,如果找到了该元素,返回true,没找到返回false。需要注意的是:我们实现的是泛型类顺序表,传递的是引用类型,引用类型比较不能使用==,而是使用equals方法

    // 判定是否包含某个元素public boolean contains(T toFind) {for (int i = 0; i < curSize; i++) {if (toFind.equals(array[i])) {return true;}}return false;}

2.5.2 查找某个元素对应的位置

循环遍历顺序表所有元素,找到了这个元素就返回下标,没找到则返回-1,该方法只返回第一次出现该元素的位置

    // 查找某个元素第一次出现位置public int indexOf(T toFind) {int index = -1;for (int i = 0; i < curSize; i++) {if (toFind.equals(array[i])) {index = i;}}return index;}

2.5.3 pos位置不合法异常

获取元素前需要判断传的参数pos的合法性,pos不能小于0,pos也不能大于等于当前顺序表个数curSize,如果pos合法,返回pos位置的元素即可。
判断pos位置是否合法,可以通过自定义异常来实现,如果pos不合法,抛出自定义的异常,通过try-catch捕获
定义一个pos位置不合法异常:

public class PosNotLegalException extends RuntimeException {public PosNotLegalException(String s) {super(s);}public PosNotLegalException() {super();}
}

2.5.4 获取pos位置的元素:

判断pos的合法性,如果不合法,抛出异常;如果合法,返回该下标元素即可

    //获取pos位置的元素public T get(int pos) {try {if (pos < 0 || pos >= curSize) {throw new PosNotLegalException("pos位置不合法");}} catch (PosNotLegalException e) {e.printStackTrace();}return (T) array[pos];}

2.6 修改数据

修改数据:将pos下标位置修改为指定的值,同样需要判断pos的合法性,如果合法直接将pos下标的值修改即可

    //将pos位置设置为valuepublic void set(int pos, T value) {if (pos < 0 || pos >= curSize) {throw new PosNotLegalException("pos位置不合法");}array[pos] = value;}

3. 全部代码

自定义的异常类(pos位置不合法异常)

public class PosNotLegalException extends RuntimeException {public PosNotLegalException(String s) {super(s);}public PosNotLegalException() {super();}
}

SeqList.java文件

public class SeqList<T> {public Object[] array;//存放数据的数组public int curSize;//当前数据个数private int Capacity = 10;//容量//初始化public SeqList() {this.array = new Object[this.Capacity];}//扩容private void dilatation() {this.array = Arrays.copyOf(this.array, 2 * this.Capacity);this.Capacity *= 2;}//尾插public void add(T data) {if (isFull()) {//如果满了,扩容dilatation();}this.array[curSize] = data;this.curSize++;}//在pos位置添加数据public void add(int pos, T data) throws PosNotLegalException {//判断pos位置合不合法try {if (pos < 0 || pos > this.curSize) {throw new PosNotLegalException("pos位置不合法");}} catch (PosNotLegalException e) {e.printStackTrace();}//如果满了,扩容if (isFull()) {dilatation();}//开始添加int cur = curSize;while (cur > pos) {array[cur] = array[cur - 1];cur--;}array[pos] = data;this.curSize++;}//头插public void addFront(T data) {//如果满了,扩容if (isFull()) {dilatation();}//如果没有元素,直接添加if (this.curSize == 0) {this.array[0] = data;this.curSize++;return;}//开始添加int cur = curSize;while (cur > 0) {array[cur] = array[cur - 1];cur--;}array[0] = data;this.curSize++;}//判断容量是否满public boolean isFull() {return this.curSize == this.Capacity;}// 判定是否包含某个元素public boolean contains(T toFind) {for (int i = 0; i < curSize; i++) {if (toFind.equals(array[i])) {return true;}}return false;}// 查找某个元素对应的位置public int indexOf(T toFind) {int index = -1;for (int i = 0; i < curSize; i++) {if (toFind.equals(array[i])) {index = i;}}return index;}//获取pos位置的元素public T get(int pos) {try {if (pos < 0 || pos >= curSize) {throw new PosNotLegalException("pos位置不合法");}} catch (PosNotLegalException e) {e.printStackTrace();}return (T) array[pos];}//判断是否为空public boolean isEmpty() {return curSize == 0;}//将pos位置设置为valuepublic void set(int pos, T value) {if (pos < 0 || pos >= curSize) {throw new PosNotLegalException("pos位置不合法");}array[pos] = value;}//移除第一次出现的keypublic void remove(T key) {int cur = -1;for (int i = 0; i < curSize; i++) {if (key.equals(array[i])) {cur = i;//记录该位置}}if (cur == -1) {System.out.println("找不到该元素");} else {//挪数据while (cur < curSize - 1) {array[cur] = array[cur + 1];cur++;}this.curSize--;}}//移除所有的keypublic void removeAll(T key) {//将所有的key都删除int fast = 0;int slow = 0;while (fast < this.curSize) {if (this.array[fast] != key) {array[slow] = array[fast];fast++;slow++;} else {fast++;}}this.curSize = slow;}//返回当前长度public int size() {return curSize;}//清空public void clear() {for (int i = 0; i < curSize; i++) {array[i] = null;}this.curSize = 0;this.Capacity = 0;}
}

今天的内容就到这里,感谢老铁们的点赞、收藏、评论~❤

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

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

相关文章

微服务之Nacos配置管理

文章目录 前言一、统一配置管理Nacos操作二、统一配置管理java操作1.引入依赖2.创建配置文件3.测试4.总结 三、Nacos配置自动更新1.添加注解RefreshScope2.使用ConfigurationProperties注解3.总结 四、Nacos多环境配置共享1.配置文件2.多种配置的优先级3.总结 总结 前言 一、统…

leetcode 150.逆波兰表达式求值

题目 思路 逆波兰表达式也是经典的栈的应用问题。 先说什么是逆波兰表达式&#xff08;也叫后缀表达式&#xff09; 我们习惯的是这样的表达式&#xff1a;1 2 / 3 ,这也叫中缀表达式。 但是对于计算机来说不好理解&#xff0c;当从左扫描到 2 的时候还需要再判断2后面是什…

STM32 | Systick定时器(第四天源码解析)

STM32 | Systick定时器(第四天)STM32 | STM32F407ZE中断、按键、灯(续第三天)1、参考delay_us代码,完成delay_ms的程序 定时器频率换算单位:1GHZ=1000MHZ=1000 000KHZ = 1000 000 000HZ 定时器定时时间:计数个数/f(频率) 或者 (1/f(频率))*计数的个数 500/1MHZ = 500/1…

C++面向对象三大特征-----继承(详细版)

目录 继承 一、继承的基础介绍 普通版网页和继承版网页的区别 语法 二、继承方式 三种继承方式 三、继承中的对象模型 四、继承中构造和析构函数 五、继承同名成员的处理方式 访问同名成员&#xff1a; 作用域写法&#xff1a; 六、继承同名静态成员的处理方式 访问…

Qt播放音乐代码示例

主界面 点击play按钮播放或暂停音乐&#xff0c;拖动进度条&#xff0c;音乐对应播放。 QWidget window;QPushButton* playButton new QPushButton("Play");// Qt 播放音乐// 创建 QMediaPlayer 对象QMediaPlayer* player new QMediaPlayer;// 指定音频文件的路径…

MySQL B+树索引 和 Redis 中跳表索引的区别

一、MySQL B树索引 和 Redis 中跳表索引 在 MySQL 中常用的索引是 B树索引&#xff0c;而 Redis 中&#xff0c;例如 zset 使用的的是跳表索引&#xff0c;两者有什么区别呢&#xff0c;MySQL 为什么不使用 跳表 呢&#xff1f;或者说 Redis 中为什么不使用 B树 呢&#xff1f…

章节10实验--Ubuntu18.04 Qt MySQL libqsqlmysql.so

前言: 内容参考《操作系统实践-基于Linux应用与内核编程》一书的示例代码和教材内容&#xff0c;所做的读书笔记。本文记录再这里按照书中示例做一遍代码编程实践加深对操作系统的理解。 引用: 《操作系统实践-基于Linux应用与内核编程》 作者&#xff1a;房胜、李旭健、黄…

golang 对接第三方接口 RSA 做签(加密) 验签(解密)

一、过程 1.调用第三方接口前&#xff0c;一般需要按规则将参数按key1value1&key2value2 阿斯克码排序,sign参数不参与加密 2.将排序并连接好的参数字符串通过我方的私钥证书&#xff08;.pem&#xff09;进行加密得到加密串&#xff0c;当然加密得到的是 []byte 字节流&…

看完就等于拿捏浮点数在内存中的储存了

诸君又该学习了&#xff0c;今天我们继续来一睹浮点数的奥妙真容。 经过前面文章对整形提升相关的解释&#xff0c;我们都对整形和字符在内存空间上的储存已经有了大概的认知&#xff0c;那么现在我们就来好好讲讲浮点数在内存中的储存规则。 目录 浮点数与整形储存的不同 …

41-Vue-webpack基础

webpack基础 前言什么是webpackwebpack的基本使用指定webpack的entry和output 前言 本篇开始来学习下webpack的使用 什么是webpack webpack: 是前端项目工程化的具体解决方案。 主要功能&#xff1a;它提供了友好的前端模块化开发支持&#xff0c;以及代码压缩混淆、处理浏览…

自定义序列化

3.2.2.自定义序列化 RedisTemplate可以接收任意Object作为值写入Redis&#xff1a; 只不过写入前会把Object序列化为字节形式&#xff0c;默认是采用JDK序列化&#xff0c;得到的结果是这样的&#xff1a; 缺点&#xff1a; 可读性差内存占用较大 我们可以自定义RedisTempla…

NASA数据集——2015 年30 米分辨率的地衣地面覆盖率模型估计值

cABoVE: Lichen Forage Cover over Fortymile Caribou Range, Alaska and Yukon, 2000-2015 文件修订日期&#xff1a;2021-07-21 数据集版本: 1 摘要 本数据集提供了美国阿拉斯加东部内陆和加拿大育空地区 Fortymile 研究区 2015 标称年 30 米分辨率的地衣地面覆盖率模型估…

YOLOv8-ROS-noetic+USB-CAM目标检测

环境介绍 Ubuntu20.04 Ros1-noetic Anaconda-yolov8虚拟环境 本文假设ROS和anaconda虚拟环境都已经配备&#xff0c;如果不知道怎么配备可以参考&#xff1a; https://blog.csdn.net/weixin_45231460/article/details/132906916 创建工作空间 mkdir -p ~/catkin_ws/srccd ~/ca…

湖北专升本报名照片需要<40kb怎么解决

湖北专升本报名照片需要<40kb怎么解决

vue 修改element-plus主题色

一、安装SCSS npm install sass --save-dev npm install sass-loader --save-dev npm install node-sass --save-dev npm install vue-style-loader --sava-dev 二、添加主题文件theme.scss forward "element-plus/theme-chalk/src/common/var.scss" with ($col…

kubernetes负载均衡-service

一、service的概念 1、什么是service 在Kubernetes中&#xff0c;pod是应用程序的载体&#xff0c;当我们需要访问这个应用时&#xff0c;可以通过Pod的IP进行访问&#xff0c;但是这里有两个问题:1、Pod的IP地址不固定&#xff0c;一旦Pod异常退出、节点故障&#xff0c;则会…

【STM32】读写BKP备份寄存器RTC实时时钟

目录 BKP BKP简介 BKP基本结构 BKP测试代码 RTC RTC简介 RTC框图 RTC基本结构 硬件电路 RTC操作注意事项 接线图 初始化 使用BKP解决只初始化一次时间 初始化参考代码 RTC设置时间 RTC读取时间 完整代码 MyRTC.c MyRTC.h main.c BKP BKP简介 BKP&#xff0…

pytorch中tensor类型转换的几个函数

目录 IntTensor转FloatTensor FloatTensor转IntTensor Tensor类型变为python的常规类型 IntTensor转FloatTensor .float函数&#xff1a; FloatTensor转IntTensor .int函数 Tensor类型变为python的常规类型 item函数

阿里云部署MySQL、Redis、RocketMQ、Nacos集群

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容MySQL集群配置云服务器选购CPU选择内存选择云盘选择ESSD AutoPL云盘块存储性能&#xff08;ESSD&#xff09; 镜像选择带宽选择密码配置注意事项 安装docker和docker-compose部署MySQL三主六从半同步集群一主二从同步集群规…

pytorch如何向tensor结尾添加元素或维度--torch.cat()、torch.unsqueeze()的用法

目录 示例1 矢量后增加元素 示例2 tensor维度增加1 示例3 另一种替代unsqueeze的方法 示例1 矢量后增加元素 使用torch.cat()函数 ptorch.Tensor([1,5,0]) ptorch.cat((p, torch.Tensor([4])), 0) 结果&#xff1a; 这里&#xff0c;cat的第一个输入变量用()包绕&#xf…