news 2026/8/24 8:00:07

线性表--02---顺序表

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
线性表--02---顺序表

顺序表

定义;

顺序表是在计算机内存中以数组的形式保存的线性表.
  • 顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元,依次存储线性表中的各个元素.
  • 使得线性表中再逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。

顺序表的实现

顺序表API设计:

顺序表的遍历:

一般作为容器存储数据,都需要向外部提供遍历的方式,因此我们需要给顺序表提供遍历方式。

在java中,遍历集合的方式一般都是用的是foreach循环,如果想让我们的SequenceList也能支持foreach循环,则需要做如下操作:

  1. 让SequenceList实现Iterable接口,重写iterator方法;
  2. 在SequenceList内部提供一个内部类SIterator,实现Iterator接口,重写hasNext方法和next方法;
迭代器模式—Iterator
packagemain.java.Algorithms.linear;importjava.util.Iterator;publicclassSequenceList<T>implementsIterable<T>{//存储元素的数组privateT[]eles;//记录当前顺序表中的元素个数privateintN;//..........省略中....................@OverridepublicIterator<T>iterator(){returnnewSIterator();}privateclassSIteratorimplementsIterator{privateintcusor;publicSIterator(){this.cusor=0;}@OverridepublicbooleanhasNext(){returncusor<N;}@OverridepublicObjectnext(){returneles[cusor++];}}}

顺序表的容量可变:

考虑容器的容量伸缩性,其实就是改变存储数据元素的数组的大小,那我们需要考虑什么时候需要改变数组的大小?

1.添加元素时:

2.移除元素时:

//根据参数newSize,重置eles的大小publicvoidresize(intnewSize){//定义一个临时数组,指向原数组T[]temp=eles;//创建新数组eles=(T[])newObject[newSize];//把原数组的数据拷贝到新数组即可for(inti=0;i<N;i++){eles[i]=temp[i];}}
System.arraycopy(temp,0,eles,0, N);

完整代码实现:

importjava.util.Iterator;publicclassSequenceList<T>implementsIterable<T>{//存储元素的数组privateT[]eles;//记录当前顺序表中的元素个数privateintN;//构造方法publicSequenceList(intcapacity){//初始化数组this.eles=(T[])newObject[capacity];//初始化长度this.N=0;}//无参构造方法,初始长度为8publicSequenceList(){//初始化数组this.eles=(T[])newObject[8];//初始化长度this.N=0;}//将一个线性表置为空表publicvoidclear(){this.eles=(T[])newObject[8];this.N=0;}//判断当前线性表是否为空表publicbooleanisEmpty(){returnN==0;}//获取线性表的长度publicintlength(){returnN;}//获取指定位置的元素publicTget(inti){if(i<0||i>=N){thrownewRuntimeException("当前元素不存在!");}returneles[i];}//向线型表中添加元素tpublicvoidinsert(Tt){//元素已经放满了数组,需要扩容if(N==eles.length){resize(2*eles.length);}eles[N++]=t;}//在i元素处插入元素tpublicvoidinsert(inti,Tt){if(i<0||i>N){thrownewRuntimeException("插入的位置不合法");}//元素已经放满了数组,需要扩容if(N==eles.length){resize(2*eles.length);}//先把i索引处的元素及其后面的元素依次向后移动一位for(intindex=N;index>i;index--){eles[index]=eles[index-1];}//再把t元素放到i索引处即可eles[i]=t;//元素个数+1N++;}//删除指定位置i处的元素,并返回该元素publicTremove(inti){if(i<0||i>N-1){thrownewRuntimeException("当前要删除的元素不存在");}//记录索引i处的值Tcurrent=eles[i];//索引i后面元素依次向前移动一位即可for(intindex=i;index<N-1;index++){eles[index]=eles[index+1];}//元素个数-1N--;if(N<eles.length/4){resize(eles.length/2);}returncurrent;}//查找t元素第一次出现的位置publicintindexOf(Tt){if(t==null){thrownewRuntimeException("查找的元素不合法");}for(inti=0;i<N;i++){if(eles[i].equals(t)){returni;}}return-1;}//根据参数newSize,重置eles的大小publicvoidresize(intnewSize){//定义一个临时数组,指向原数组T[]temp=eles;//创建新数组eles=(T[])newObject[newSize];//把原数组的数据拷贝到新数组即可for(inti=0;i<N;i++){eles[i]=temp[i];}}@OverridepublicIterator<T>iterator(){returnnewSIterator();}privateclassSIteratorimplementsIterator{privateintcusor;publicSIterator(){this.cusor=0;}@OverridepublicbooleanhasNext(){returncusor<N;}@OverridepublicObjectnext(){returneles[cusor++];}}}

测试

importjava.util.Iterator;publicclassSequenceListTest{publicstaticvoidmain(String[]args){//创建顺序表对象SequenceList<String>sl=newSequenceList<>(10);System.out.println("-----------测试插入获取-------------");//测试插入 获取sl.insert("姚明");sl.insert("科比");sl.insert("麦迪");sl.insert(1,"詹姆斯");for(inti=0;i<sl.length();i++){System.out.println(sl.get(i));}System.out.println("-----------测试遍历-------------");//测试删除StringremoveResult=sl.remove(0);System.out.println("删除的元素是:"+removeResult);//测试遍历Iterator<String>iterator=sl.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}//测试清空System.out.println("-----------测试清空-------------");sl.clear();System.out.println("清空后的线性表中的元素个数为:"+sl.length());for(Stringstr:sl){System.out.println(str);}}}

分析:

顺序表的时间复杂度:

get(i):

insert(int i,T t):

remove(int i):

扩容操作:

由于顺序表的底层由数组实现,数组的长度是固定的,所以在操作的过程中涉及到了容器扩容操作。这样会导致顺序表在使用过程中的时间复杂度不是线性的,在某些需要扩容的结点处,耗时会突增,尤其是元素越多,这个问题越明显

顺序表查找效率高,插入和删除效率低

java中ArrayList实现:

Java集合—03–List


为什么有ArrayList,还要自己编写顺序表?

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/24 7:59:28

排序--06---快速排序

快速排序 定义: 快速排序是对冒泡排序的一种改进。它的基本思想是&#xff1a;通过一趟排序将要排序的数据分割成独立的两部分&#xff0c;其中一部分的所有数据都比另外一部分的所有数据都要小&#xff0c;然后再按此方法对这两部分数据分别进行快速排序&#xff0c;整个排序过…

作者头像 李华
网站建设 2026/8/24 7:59:26

排序--05---归并排序

复习递归正式学习归并排序之前&#xff0c;我们得先复习一下递归算法。定义&#xff1a; 定义方法时&#xff0c;在方法内部调用方法本身&#xff0c;称之为递归.作用&#xff1a; 它通常把一个大型复杂的问题&#xff0c;层层转换为一个与原问题相似的&#xff0c;规模较小的问…

作者头像 李华
网站建设 2026/8/24 7:59:24

基础--01---算法----概述

什么是算法&#xff1f; 官方解释&#xff1a; 算法是指解题方案的准确而完整的描述&#xff0c;是一系列解决问题的清晰指令&#xff0c;算法代表着用系统的方法解决问题的策略机制。也就是说&#xff0c;能够对一定规范的输入&#xff0c;在有限时间内获得所要求的输出。算法…

作者头像 李华
网站建设 2026/8/24 7:57:54

Unity文件操作全解析:从EditorUtility到跨平台自定义UI实现

1. 项目概述&#xff1a;为什么Unity文件操作值得深究&#xff1f;在Unity开发中&#xff0c;无论是编辑器工具开发、运行时数据管理&#xff0c;还是项目配置导入导出&#xff0c;文件的选择与保存都是一个高频且基础的需求。新手可能会直接想到EditorUtility.OpenFilePanel&a…

作者头像 李华
网站建设 2026/8/24 7:51:28

工业AI研究可审计实验记录系统:从轨迹到证据的范式变革

1. 项目概述&#xff1a;当工业研究遇上“可审计”的实验记录最近和几个在大型化工、材料研发机构做算法落地的朋友聊天&#xff0c;大家不约而同地提到了同一个痛点&#xff1a;实验室里跑出来的AI模型&#xff0c;到了产线上怎么解释&#xff1f;评审会上&#xff0c;面对“为…

作者头像 李华
网站建设 2026/8/24 7:51:01

双非开发者如何构建AI Agent工程化能力:从RAG到LangGraph的实战进阶

最近和几位刚入行的朋友聊起找工作&#xff0c;发现一个很有意思的现象&#xff1a;很多人把“Agent开发”理解成了“会用几个框架”&#xff0c;简历上罗列着LangChain、LangGraph、RAG&#xff0c;但一问到“你做的Agent真正解决了什么业务问题”、“它上线后怎么维护”、“遇…

作者头像 李华