数据结构之顺序表(java版)

目录

一.线性表

1.1线性表的概念

二.顺序表 

2.1顺序表的概念

2.2顺序表的实现

1.顺序表的接口

1.2顺序表的功能实现

1.顺序表初始化

2.新增元素功能:

3.清空顺序表是否为空&&获取顺序表长度&&打印顺序表:

4.判断是否包含某个元素&&查找某个元素的对应位置

5.在指定位置新增元素

6.获取pos位置的元素&&给pos位置的元素值设为value

7.删除第一次出现关键字key

2.3顺序表完整代码 

三.java中的ArrayList


一.线性表

1.1线性表的概念

线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表有:顺序表、链表、栈、队列。

线性表在逻辑上是线性结构,也就是连续的一条直线。但是在物理结构上不一定是连续的,线性表在物理上存储时,通常以数组和链式结构存储。

本章我们主要讲的是顺序表。


二.顺序表 

2.1顺序表的概念

顺序表是用一段物理地址连续的存储单元依次存放数据元素的线性结构,一般采用数组存储。在数组上完成数据的增删查改。

2.2顺序表的实现

1.顺序表的接口

有了接口,可以实现代码的复用。

package MyArraylistto;public interface IList {// 新增元素,默认在数组最后新增public void add(int data);// 在 pos 位置新增元素public void add(int pos, int data);// 判定是否包含某个元素public boolean contains(int toFind);// 查找某个元素对应的位置public int indexOf(int toFind);// 获取 pos 位置的元素public int get(int pos);// 给 pos 位置的元素设为 valuepublic void set(int pos, int value);//删除第一次出现的关键字keypublic void remove(int toRemove);// 获取顺序表长度public int size() ;// 清空顺序表public void clear();// 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的public void display();
}

1.2顺序表的功能实现

首先,我们需要创建一个类并且实现接口中的方法。

MyArraylistf.java

1.顺序表初始化

在此之前,我们需要为顺序表开辟一定的空间内存。

 private int[] elems; // 用于存储数组元素的内部数组private int size; // 表示当前数组中元素的数量public MyArraylistf(){elems = new int[10]; // 初始化内部数组 elems,容量为10size = 0; // 将数组元素数量初始化为0}
2.新增元素功能:

我们在插入元素之前需要先判断我们所提供的内存是否已经用完了,如果用完了,我们可以使用Arrays.copyOf(原数组,开辟的空间大小).进行扩容。在插入数据元素后,我们需要让size+1。如下

  public  void add(int data){if(size== elems.length){elems= Arrays.copyOf(elems,2*elems.length);}elems[size]=data;this.size++;}
3.清空顺序表是否为空&&获取顺序表长度&&打印顺序表:

1.清空顺序表长度:我们直接让size置为空。

2.获取顺序表长度:我们直接返回size的大小即可。

 public void clear(){//清空顺序表this.size=0;}public int size(){//返回顺序表元素个数return this.size;}
public void display(){for(int i=0;i<this.size;i++){System.out.print(elems[i]+" ");}System.out.println();}
4.判断是否包含某个元素&&查找某个元素的对应位置

判断是否包含某个元素,只需要遍历一遍顺序表即可,如果存在返回true,反之,返回false.

查找元素的位置,也是遍历一遍顺序表,找到返回对应下标即可。

  // 判定是否包含某个元素public boolean contains(int toFind){for(int i=0;i<this.size;i++){if(elems[i]==toFind){return true;}}return false;}// 查找某个元素对应的位置public int indexOf(int toFind){for(int i=0;i<this.size;i++){if(elems[i]==toFind){return i;}}return -1;}
5.在指定位置新增元素

我们在指定位置新增元素时,需要考虑:

1.插入的位置是否合法,如果小于0或者大于顺序表的最大长度,则抛出异常。

2.位置没有问题,那就需要判断顺序表是否已满,如果满了,进行扩容。

3.我们需要将pos位置以后的数据全部后移以为,才能进行插入。

   /* 检查给定的位置是否合法。* 如果位置小于0或大于当前数组大小,则抛出PosNotlegalException异常。* @param pos 要检查的位置* @throws PosNotlegalException 如果位置不合法,则抛出此异常*/private void checkPos(int pos)throws PosNotlegalException{if(pos<0||pos>size){throw new PosNotlegalException("位置不合法");}}/*** 在指定的位置插入一个元素。* 首先会检查位置是否合法,然后将元素插入到指定位置,后续元素依次后移。* 如果数组已满,则会自动扩展数组大小。* @param pos 插入元素的位置* @param data 要插入的元素值*/public void add(int pos, int data){// 判断位置是否合法try{checkPos(pos);}catch (PosNotlegalException e){e.printStackTrace();}// 检查顺序表是否已满,若满则扩展一倍容量if(size== elems.length){elems= Arrays.copyOf(elems,2*elems.length);}// 将插入位置之后的元素依次后移for(int i=size;i>pos;i--){elems[i]=elems[i-1];}// 在指定位置插入元素elems[pos]=data;// 更新数组大小size++;}
6.获取pos位置的元素&&给pos位置的元素值设为value

1.获取pos位置的元素:我们严谨一点,需要考虑pos是否合法,不合法抛出异常。

2.给pos位置的值设为value:我们与上相同,判断完,直接让pos位置的值改为value。 

 // 获取 pos 位置的元素public int get(int pos){try {checkPos(pos);}catch(PosNotlegalException e){e.printStackTrace();}return elems[pos];}// 给 pos 位置的元素设为 valuepublic void set(int pos, int value){try {checkPos(pos);}catch(PosNotlegalException e){e.printStackTrace();}elems[pos]=value;}
7.删除第一次出现关键字key

我们这里可以采用双层遍历的方式进行删除。

在外循环遍历的时候,如果数组中的元素与key相同,则进入内循环,将i位置的数据进行覆盖,我们需要遍历size-1次。

扩展:如果要删除所有出现key的元素,我们将return去掉即可

  /*** 删除数组中第一次出现的指定元素。* @param toRemove 需要删除的元素。*/public void remove(int toRemove){// 遍历数组,寻找第一个匹配的元素for(int i=0;i<this.size;i++){if(elems[i]==toRemove){// 将找到元素后的元素依次向前移动for(int j=i;j<this.size-1;j++){elems[j]=elems[j+1];}// 调整数组大小,表示已删除一个元素size--;return;}}}//删除数组中出现toRemove的全部元素public void removeAll(int toRemove){for(int i=0;i<this.size;i++){if(elems[i]==toRemove){for(int j=i;j<this.size-1;j++){elems[j]=elems[j+1];}size--;}}}

至此,我们把接口中的方法全部进行了实现。我们可以在main函数中进行测试一下。

2.3顺序表完整代码 

测试类:TTest.java

package MyArraylistto;public class TTest {public static void main(String[] args) {MyArraylistf list = new MyArraylistf();list.add(1);list.add(1);list.add(1);list.add(1);list.add(2);list.add(2,2);list.display();System.out.println("===========");list.removeAll(2);list.display();}
}

顺序功能实现:MyArraylistf.java

package MyArraylistto;import java.util.Arrays;public class MyArraylistf implements IList{/*** MyArraylistf 类用于实现一个简单的数组列表。* 该类内部使用整型数组存储元素,并且能够动态调整数组大小。*/private int[] elems; // 用于存储数组元素的内部数组private int size; // 表示当前数组中元素的数量/*** MyArraylistf 构造函数。* 初始化内部数组 elems 为长度为 10 的整型数组,并将 size 设置为 0。*/public MyArraylistf(){elems = new int[10]; // 初始化内部数组 elems,容量为10size = 0; // 将数组元素数量初始化为0}public  void add(int data){if(size== elems.length){elems= Arrays.copyOf(elems,2*elems.length);}elems[size]=data;this.size++;}/*** 检查给定的位置是否合法。* 如果位置小于0或大于当前数组大小,则抛出PosNotlegalException异常。* @param pos 要检查的位置* @throws PosNotlegalException 如果位置不合法,则抛出此异常*/private void checkPos(int pos)throws PosNotlegalException{if(pos<0||pos>size){throw new PosNotlegalException("位置不合法");}}/*** 在指定的位置插入一个元素。* 首先会检查位置是否合法,然后将元素插入到指定位置,后续元素依次后移。* 如果数组已满,则会自动扩展数组大小。* @param pos 插入元素的位置* @param data 要插入的元素值*/public void add(int pos, int data){// 判断位置是否合法try{checkPos(pos);}catch (PosNotlegalException e){e.printStackTrace();}// 检查顺序表是否已满,若满则扩展一倍容量if(size== elems.length){elems= Arrays.copyOf(elems,2*elems.length);}// 将插入位置之后的元素依次后移for(int i=size;i>pos;i--){elems[i]=elems[i-1];}// 在指定位置插入元素elems[pos]=data;// 更新数组大小size++;}// 获取 pos 位置的元素public int get(int pos){try {checkPos(pos);}catch(PosNotlegalException e){e.printStackTrace();}return elems[pos];}// 给 pos 位置的元素设为 valuepublic void set(int pos, int value){try {checkPos(pos);}catch(PosNotlegalException e){e.printStackTrace();}elems[pos]=value;}//删除第一次出现的关键字keypublic void remove(int toRemove){for(int i=0;i<this.size;i++){if(elems[i]==toRemove){for(int j=i;j<this.size-1;j++){elems[j]=elems[j+1];}size--;return;}}}public void removeAll(int toRemove){for(int i=0;i<this.size;i++){if(elems[i]==toRemove){for(int j=i;j<this.size-1;j++){elems[j]=elems[j+1];}size--;}}}// 判定是否包含某个元素public boolean contains(int toFind){for(int i=0;i<this.size;i++){if(elems[i]==toFind){return true;}}return false;}// 查找某个元素对应的位置public int indexOf(int toFind){for(int i=0;i<this.size;i++){if(elems[i]==toFind){return i;}}return -1;}public void clear(){//清空顺序表this.size=0;}public int size(){//返回顺序表元素个数return this.size;}public void display(){for(int i=0;i<this.size;i++){System.out.print(elems[i]+" ");}System.out.println();}
}

接口:IList.java 

package MyArraylistto;public interface IList {// 新增元素,默认在数组最后新增public void add(int data);// 在 pos 位置新增元素public void add(int pos, int data);// 判定是否包含某个元素public boolean contains(int toFind);// 查找某个元素对应的位置public int indexOf(int toFind);// 获取 pos 位置的元素public int get(int pos);// 给 pos 位置的元素设为 valuepublic void set(int pos, int value);//删除第一次出现的关键字keypublic void remove(int toRemove);// 获取顺序表长度public int size() ;// 清空顺序表public void clear();// 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的public void display();
}

三.java中的ArrayList 

在集合框架中,ArrayList是一个普通的类,实现了List接口,具体框架如下:

 说明

1. ArrayList是以泛型方式实现的,使用时必须要先实例化

2. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问 

3. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的

4. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的

5. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者 CopyOnWriteArrayList

6. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表

 3.1ArrayList的使用

java中所提供的方法在ArrayList (Java 平台 SE 8 ) (oracle.com)可进行查看。

四.顺序表的缺陷

1.ArrayList底层使用连续的空间,任意位置的插入或删除元素时,需要将该位置后序元素整体向前或者向后移动,时间复杂度为O(N)。

2.扩容的时候需要申请新的空间,拷贝数据,释放旧空间,会有不小的损耗。

3.扩容一般是呈2倍的增长,所以一定会有空间的浪费。例如,你开辟了50的空间,等满了以后扩容到100,这时再利用10个空间,但后面的空间没有使用,就浪费了45个数据空间。

但是我们使用链表不会有这样的问题。

链表在插入数据的时候是生成一个个数据空间,通过指针连接起来,这样就不会造成空间的浪费。

同时,链表在插入和删除数据的效率比顺序表快。

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

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

相关文章

C语言 | Leetcode C语言题解之第47题全排列II

题目&#xff1a; 题解&#xff1a; int* vis;void backtrack(int* nums, int numSize, int** ans, int* ansSize, int idx, int* perm) {if (idx numSize) {int* tmp malloc(sizeof(int) * numSize);memcpy(tmp, perm, sizeof(int) * numSize);ans[(*ansSize)] tmp;return…

食用油5G智能工厂数字孪生可视化平台,推进食品制造业数字化转型

食用油5G智能工厂数字孪生可视化平台&#xff0c;推进食品制造业数字化转型。在食用油产业中&#xff0c;数字化转型已成为提升生产效率、优化供应链管理、确保产品质量和满足消费者需求的关键。食用油5G智能工厂数字孪生可视化平台作为这一转型的重要工具&#xff0c;正在推动…

四川赢涟电子商务有限公司是做什么的?

在当今数字化浪潮中&#xff0c;电子商务以其独特的魅力和无限潜力&#xff0c;成为了商业领域的新宠。而在这股潮流中&#xff0c;四川赢涟电子商务有限公司以其对抖音电商的深入研究和专业服务&#xff0c;成为了行业内的佼佼者。 一、深耕抖音&#xff0c;领跑电商新赛道 四…

隆道再次当选中招协招标采购数字化专委会执行主任单位

4月19日&#xff0c;中国招标投标协会招标采购数字化专业委员会换届会议暨第二届第一次工作会议在宁波召开。经过大会提名、审议和表决&#xff0c;北京隆道网络科技有限公司再次当选为招标采购数字化专委会执行主任单位。 中国招标投标协会招标采购数字化专业委员会&#xff0…

uView u-parse 在nvue页面中无作用踩坑

问题起因&#xff1a; 在uni-app开发的app nvue页面中有需要回显渲染字符串形式的富文本内容 但使用v-html和uniapp的rich-text组件都无法起到作用&#xff0c;就想到了使用uView中u-parse进行尝试。 uView我是使用uniApp插件市场导入的方式将插件导入项目的uni_modules中 …

上海·得物技术沙龙-「无线技术」专场报名开启!

本次无线沙龙聚焦于最新的技术趋势和实践&#xff0c;将在上海/线上为你带来四个令人期待的演讲话题&#xff0c;包括&#xff1a;《快手主App启动接口带宽优化实践》、《得物App视频体验优化实践》、《Chromium内核架构和网络库优化介绍》、《得物App发热监控实践》。相信这些…

聚观早报 | 百度地图V20正式发布;OPPO K12细节曝光

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 4月24日消息 百度地图V20正式发布 OPPO K12细节曝光 Meta宣布开放VR系统 三星 Galaxy Ring提供多种尺寸 Redmi …

【七】jmeter5.5+influxdb2.0+prometheus+grafana

参考文章&#xff1a;https://blog.csdn.net/wenxingchen/article/details/126892890 https://blog.csdn.net/Zuo19960127/article/details/119726652 https://blog.csdn.net/shnu_cdk/article/details/132182858 promethus参考 由于自己下载的是infuldb2.0&#xff0c;所以按照…

权益商城系统源码 现支持多种支付方式

权益商城系统源码&#xff0c;支持多种支付方式&#xff0c;后台商品管理&#xff0c;订单管理&#xff0c;串货管理&#xff0c;分站管理&#xff0c;会员列表&#xff0c;分销日志&#xff0c;应用配置。 上传到服务器&#xff0c;修改数据库信息&#xff0c;导入数据库&…

SQLAIchemy 异步DBManager封装-03得心应手

前言 SQLAIchemy 异步DBManager封装-01入门理解SQLAIchemy 异步DBManager封装-02熟悉掌握 在前两篇文章中&#xff0c;我们详细介绍了SQLAlchemy异步DBManager的封装过程。第一篇文章帮助我们入门理解了整体的封装结构和思路&#xff0c;第二篇文章则帮助我们更加熟悉和掌握了这…

ollama运行自定义模型

ollama有默认的模型&#xff0c;那么怎么运行自定义模型&#xff0c;自己选择下载模型&#xff0c;然后运行呢 下面说下自定义模型的运行 1. 首先下载模型文件 ollama 可以直接加载gguf文件后缀的模型这些模型&#xff0c;你可以通过下面两个站点搜索即可。 https://huggin…

CUDA的开发框架

CUDA的开发框架主要提供了一系列工具和库&#xff0c;使得开发者可以充分利用NVIDIA GPU进行高效的并行计算。以下是CUDA开发框架的一些关键组成部分。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.CUDA核心库&#xff1a;这些是构…