当前位置: 首页 > news >正文

数据结构-2.顺序表

1.线性表

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

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

2.顺序表

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

2.1接口的实现

public class MyArrayList {private int[] elem;//用来存放数据元素private int usedSize;//代表当前顺序表当中的有效数据个数private static final int DEFAULT_SIZE = 10;//顺序表的空间大小public MyArrayList() {this.elem = new int[DEFAULT_SIZE];}//自给容量public MyArrayList(int initCapacity) {this.elem = new int[initCapacity];}//判断顺序表空间是否装满了public boolean isFull() {if(this.usedSize == this.elem.length) {return true;}return false;}// 新增元素,默认在数组最后新增public void add(int data) {//进入if说明顺序表空间不足,需要扩容if(isFull()) {this.elem = Arrays.copyOf(this.elem,2*this.elem.length);}//顺序表空间足够,还没满this.elem[this.usedSize] = data;this.usedSize++;}// 在 pos 位置新增data元素public void add(int pos, int data) {if(pos < 0 || pos > this.usedSize) {throw new RuntimeException(pos+" 位置不合法! ");//System.out.println("位置不合法! ");//return;}//顺序表空间不足if(this.isFull()) {this.elem = Arrays.copyOf(this.elem,2*this.elem.length);}//顺序表空间足够int tmp = this.usedSize;while(tmp > pos) {this.elem[tmp] = this.elem[tmp-1];tmp--;}this.elem[pos] = data;this.usedSize++;}// 判定是否包含某个元素public boolean contains(int toFind) {for (int i = 0; i < this.usedSize; i++) {//如果是两个引用类型的数据判断是否相等,则用equals或者compareTo//区别就是equals的返回值是true或者false而compareTo的返回值是intif(this.elem[i] == toFind) {return true;}}return false;}// 查找某个元素对应的位置public int indexOf(int toFind) {for (int i = 0; i < this.usedSize; i++) {//如果是两个引用类型的数据判断是否相等,则用equals或者compareTo//区别就是equals的返回值是true或者false而compareTo的返回值是intif(this.elem[i] == toFind) {return i;}}return -1;}// 获取 pos 位置的元素public int get(int pos) {//pos不合法checkPos(pos);//pos合法return this.elem[pos];}// 给 pos 位置的元素设为 valuepublic void set(int pos, int value) {checkPos(pos);this.elem[pos] = value;}private void checkPos(int pos) {if(pos < 0 || pos >= this.usedSize) {throw new RuntimeException(pos+" 位置不合法! ");}}//删除第一次出现的关键字keypublic void remove(int toRemove) {int index = indexOf(toRemove);if(index == -1) {System.out.println("没有这个数据! ");return;}while(index < usedSize-1) {this.elem[index] = this.elem[index+1];index++;}usedSize--;}// 获取顺序表长度public int size() {return this.usedSize;}// 清空顺序表public void clear() {this.usedSize = 0;}// 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的public void display() {for (int i = 0; i < this.usedSize; i++) {System.out.print(elem[i] + " ");}System.out.println();}

温馨提示: 初学者最好自己能实现顺序表的接口,后面使用ArrayList类才不至于只知其一不知其二.

3.AraayList介绍

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

说明:

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

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

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

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

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

CopyOnWriteArrayList

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

4.ArrayList的使用

4.1ArrayList的构造

ArrayList()无参构造很容易,就不做解释了, 其实就跟2.1中MyArryList的无参构造一样,名字一换就行了.

2.重点解释第二个构造方法.

List<Integer> list2 = new LinkedList<>();list2.add(1);list2.add(2);list2.add(3);List<Integer> list3 = new ArrayList<>(list2);list3.add(44);System.out.println(list3);

发现list3中包含list2的元素,  构造出来的新的顺序表list3包含list2中所有的元素, 这就是这种构造方法的意义所在.

4.2 ArrayList常见操作

ArrayList 虽然提供的方法比较多, 但是常用方法如下所示:

还有三个常用方法 : 

int   indexOf(Object o)    返回第一个o所在下标
int   lastIndexOf(Object o)     返回最后一个o的下标
List<E>  subList(int fromlndex, int tolndex)      截取部分list

  以下是set方法和 subList方法的代码示例:

ArrayList<Integer> list1 = new ArrayList<>();list1.add(666);list1.add(321);list1.add(43);list1.add(123);list1.add(32);list1.add(55);List<Integer> list2 = list1.subList(1,4);//[1,4)list2.set(0,555);System.out.println(list2);//一般情况下,能够直接通过sout输出引用指向对象当中的内容的时候,//此时一定重写了toString方法,要么是父类,要么是自己重写了

其余方法不做代码解释, 自行实现即可

4.3ArrayList的遍历

ArrayList 可以使用三种方式遍历: for循环 + 下标, for-each , 使用迭代器.

for (int i = 0; i < list1.size(); i++) {System.out.print(list1.get(i)+ " ");}System.out.println();System.out.println("===========================");//3.for-each遍历for(Integer x : list1) {System.out.print(x + " ");}System.out.println();System.out.println("============================");//4.迭代器遍历//第一种写法:(父类)/**/Iterator<Integer> it = list1.iterator();while(it.hasNext()) {System.out.print(it.next() + " ");}System.out.println();//第二种写法:(子类)ListIterator<Integer> listIterator = list1.listIterator();while(listIterator.hasNext()) {System.out.print(listIterator.next() + " ");}System.out.println();System.out.println("===================================");//从后往前遍历:ListIterator<Integer> listIterator2 = list1.listIterator(list1.size());while(listIterator.hasPrevious()) {System.out.print(listIterator2.previous() + " ");}System.out.println();

注意: 

1. ArrayList最长使用的遍历方式是: for循环+下标 以及 foreach

2. 迭代器是设计模式的一种, 后面的文章再细说

4.4ArrayList的扩容机制

从上图可以看出,即使list的长度为1,空间已满,还是可以往里添加元素. 其中的玄机一定在add方法中.

鼠标放在add上,按住ctrl(键盘最左下),鼠标左键点过去可以看到 ↓

刚开始没add时,size = 0;

所以,  minCapacity = size + 1 = 1;

补充:  Java中 在写AarryList时, 就定义了一个常量 DEFAULT_CAPACITY = 10; 同样的,在这里也可以发现  elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA  不相信可以自查.

 

继续解释扩容机制:

总结: 

1. 检测是否真正需要扩容, 如果是调用grow准备扩容

2. 预估需要的空间大小

 初步预估按照1.5倍大小扩容

 如果需要的大小超过预估的1.5倍大小,则按照所需大小扩容

3. 使用copyOf进行扩容

5.ArrayList的具体使用

5.1杨辉三角

public List<List<Integer>> generate(int numRows) {List<List<Integer>> ret = new ArrayList<>();List<Integer> row = new ArrayList<>();row.add(1);ret.add(row);//上面已经处理完第一行了//下面开始处理第二行for (int i = 1; i < numRows; i++) {List<Integer> curRow = new ArrayList<>();curRow.add(1);//新的一行的第一个值//这里处理中间列//拿到上一行List<Integer> prevRow = ret.get(i-1);for (int j = 0; j < i; j++) {int x = prevRow.get(j) + prevRow.get(j-1);curRow.add(x);}curRow.add(1);//新的一行的最后一个值ret.add(curRow);}return ret;}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Delta Function的简单介绍
  • 关于less的基本使用
  • Java设计模式—面向对象设计原则(一) ----->开闭原则OCP(完整详解,附有代码+案例)
  • re题(27)BUUFCTF-[MRCTF2020]Transform
  • C++速通LeetCode简单第18题-杨辉三角(全网唯一递归法)
  • 如何快速解决程序中的BUG
  • 商淘云九周年 分账系统助力企业合规发展
  • 深度学习数据集交通类常见图像分类、目标检测、分割图像数据集(深度学习数据集 - 交通类解决方案)
  • PHP环境搭建详细教程
  • 中秋献礼!2024年中科院一区极光优化算法+分解对比!VMD-PLO-Transformer-LSTM多变量时间序列光伏功率预测
  • 2021 年 6 月青少年软编等考 C 语言二级真题解析
  • QT Mode/View之View
  • 【webpack4系列】编写可维护的webpack构建配置(四)
  • Ubuntu 安装包下载(以20版本 阿里镜像站为例子)
  • Spring Boot-静态资源管理问题
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • java8-模拟hadoop
  • JAVA多线程机制解析-volatilesynchronized
  • Java精华积累:初学者都应该搞懂的问题
  • JDK9: 集成 Jshell 和 Maven 项目.
  • k8s如何管理Pod
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • PHP 的 SAPI 是个什么东西
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • TCP拥塞控制
  • windows下使用nginx调试简介
  • 关于 Cirru Editor 存储格式
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 老板让我十分钟上手nx-admin
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 《码出高效》学习笔记与书中错误记录
  • 昨天1024程序员节,我故意写了个死循环~
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • $refs 、$nextTic、动态组件、name的使用
  • (160)时序收敛--->(10)时序收敛十
  • (2024,LoRA,全量微调,低秩,强正则化,缓解遗忘,多样性)LoRA 学习更少,遗忘更少
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (苍穹外卖)day03菜品管理
  • (排序详解之 堆排序)
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET MVC第三章、三种传值方式
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .Net6支持的操作系统版本(.net8已来,你还在用.netframework4.5吗)
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • @Conditional注解详解
  • @NestedConfigurationProperty 注解用法
  • [ vulhub漏洞复现篇 ] ThinkPHP 5.0.23-Rce
  • []使用 Tortoise SVN 创建 Externals 外部引用目录
  • [<事务专题>]