数据结构-2.顺序表

devtools/2024/9/23 15:24:32/

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;}


http://www.ppmy.cn/devtools/116060.html

相关文章

Rocky Linux 9 中添加或删除某个网卡的静态路由的方法

使用ip命令配置临时路由 添加静态路由 ip route add <目的网络> via <下一跳IP> dev <网卡接口名称>例: 给eth0网卡添加一个到达 192.168.2.0/24 网络&#xff0c;下一跳为 192.168.1.254 的路由 ip route add 192.168.2.0/24 via 192.168.1.254 dev eth0…

卡尔曼滤波中Q和R与噪声的关系

卡尔曼滤波 一种用于估计系统状态的递归滤波器&#xff0c;通过融合传感器测量和系统模型&#xff0c;提供系统状态的最优估计。 Q和R是什么 在卡尔曼滤波中&#xff0c;Q和R分别表示过程噪声和测量噪声的协方差矩阵。 Q Q Q矩阵&#xff08;过程噪声协方差矩阵&#xff09;…

git 问题 --- fatal: detected dubious ownership in repository at

在通过 Git Bash 提交项目代码时输入 git pull 或git add . 命令后&#xff0c;报错&#xff1a;fatal: detected dubious ownership in repository at 这是因为该项目的所有者与现在的用户不一致 比如说&#xff1a; 该项目的所有者是 Administrator&#xff0c;而当前用户是…

监控易监测对象及指标之:Kubernetes(K8s)集群的全方位监控策略

随着Kubernetes&#xff08;K8s&#xff09;在云原生架构中的广泛应用&#xff0c;确保集群的高效、稳定运行变得至关重要。监控作为运维管理的核心&#xff0c;对于保障Kubernetes集群的性能和可用性具有不可替代的作用。本文基于监控易的监控指标&#xff0c;探讨了对Kuberne…

数据结构-3.2.栈的顺序存储实现

一.顺序栈的定义&#xff1a;top指针指向栈顶元素 1.图解&#xff1a; 2.代码&#xff1a; #include<stdio.h> #define MaxSize 10 //定义栈最多存入的元素个数 ​ typedef struct {int data[MaxSize]; //静态数组存放栈中元素int top; //栈顶指针 } SqStack; ​ int…

WAN广域网技术--PPP和PPPoE

广域网基础概述 广域网&#xff08;Wide Area Network&#xff0c;WAN&#xff09;是一种覆盖广泛地区的计算机网络&#xff0c;它连接不同地理位置的计算机、服务器和设备。广域网通常用于连接不同城市、州或国家之间的网络&#xff0c;它通过互联网服务提供商&#xff08;ISP…

【农信网-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

【图虫创意-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…