数据结构-ArrayList和顺序表

1.线性表

线性表是n个具有相同类型的数据元素所组成的有限序列,当n=0时,线性表为一个空表。

常见的线性表:顺序表,链表,栈和队列...

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

2.顺序表 

2.1 什么是顺序表 

顺序表是一段连续的存储单元来依次存储线性表中的数据元素。一般情况下采用数组存储。

2.2 顺序表的特点 

1.存储连续:顺序表的存储单元在内存中是连续的,这意味着每个元素的地址都是相邻连续的

2.随机访问:由于存储单元是连续的,可以通过元素的下标直接访问该位置的元素,时间复杂度为O(1)

3.存储密度高:顺序表的存储单元只存储数据元素本身,没有额外的存储开销

2.3 实现一个顺序表

public class MySequentialList{private int[] array;private int size;//默认构造方法MySequentialList(){}//将顺序表的容量设为initCapacityMySequentialList(int initCapacity){}//在数组末尾新增一个元素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(){}
}

实现的思路:

1.MySequentialList(int initCapacity)

只需要将数组初始化大小为initCapacity即可

2.add(int data)

在数组最后的位置新增元素,要注意数组是否已满,如果已满,就要对数组进行扩容操作

3.add(int pos,int data)

首先要判断插入位置pos是否合法,如果pos小于0或pos大于数组的长度,则位置不合法要进行异常处理。如果位置合法,还要判断数组是否已满,进行插入操作时,要注意先将原pos以及pos后面的元素全都向后移动一位,再进行插入操作,如果直接插入,则只是单纯的元素覆盖。插入后,数组的长度加1

4.contains(int toFind)

判断是否包含某个元素,只需要遍历数组并进行比较,看数组中是否有存在要查找的元素,如果有,则返回true,没有则返回false

5.indexOf(int toFind)

遍历数组,看数组中是否存在要查找的元素,如果存在,则返回给元素位置的下标,如果不存在,则返回-1

6.get(int pos)

获取pos位置的元素,首先要判断pos位置是否合法,如果pos小于0或者pos大于数组的长度,则pos不合法,返回-1。如果合法,直接返回下标为pos的元素

7.set(int pos,int value)

给pos位置的元素设置为value,单纯的进行对应下标元素覆盖即可

8.remove(int toRemove)

删除第一次出现关键字key,遍历数组,看key是否存在。如果不存在,则返回-1。如果存在,只需要将该位置后面的所有元素先前移动一位即可

9.size()

直接返回数组的有效长度,有效长度指的是数组中有效元素的个数,不是单纯的数组长度

10.clear()

清空顺序表,重新初始化数组,并将数组的长度置为0

我们后续以ArrayList的实现为例。

3.ArrayList

3.1 什么是ArrayList

在集合框架中,ArrayList是 Java 标准库中的一个非常常用的类,它实现了 List接口,提供了动态数组的功能。 ArrayList内部使用数组来存储元素,因此它具备顺序表的所有特点,是顺序表的一种实现。

 

说明:

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

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

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

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

5.ArrayList是线程不安全的,在单线程下可以使用

6.ArrayList是通过动态的数组实现的,是一段连续的空间,并且可以进行扩容

3.2 ArrayList的构造方法

方法解释
ArrayList()无参构造
ArrayList(Collection<? extends E> c)利用其他Collection构建ArrayList
ArrayList(int initialCapacity)指定顺序表初始容量

 代码演示:

public class Test {public static void main(String[] args) {//无参构造List<Integer> list1=new ArrayList<>();//利用其他Collection构建ArrayListArrayList<Integer> arrayList=new ArrayList<>();List<Integer> list2=new ArrayList<>(arrayList);//指定顺序表容量List<Integer> list3=new ArrayList<>(10);}
}

3.3 ArrayList的常见操作

ArrayList常见的方法

方法解释
boolean add(E,e)在尾部插入元素e
void add(int index,E e)将元素e插入到下标为index的位置
boolean addAll(Collection<? extends E> c)在尾部插入c中的所有元素
E remove(int index)删除index位置的元素
boolean remove(Object o)删除遇到第一个为o的元素
E get(int index)获取下表为index的元素
E set(int index,E e)将下表为index位置的元素设置为e
void clear()清空所有元素
boolean contains(Object o)判断o是否在线性表中
int indexOf(Object o)返回第一个o所在的下标
int lastIndexOf(Object o)返回最后一个o所在的下标
List<E> subList(int fromIndex,int toIndex)截取部分list

代码演示:

import java.util.ArrayList;
import java.util.List;public class Test {public static void main(String[] args) {List<Integer> list=new ArrayList<>();System.out.println(list);//在尾部插入元素list.add(1);list.add(5);list.add(3);list.add(5);list.add(10);System.out.println(list);//在下标为2的位置增加元素list.add(2,4);System.out.println(list);//删除下标为2的元素list.remove(2);System.out.println(list);//删除遇到的第一个5元素Integer a=5;list.remove(a);System.out.println(list);//获取下标为1的元素int e=list.get(1);System.out.println(e);//将下标为1的元素设置为99list.set(1,99);System.out.println(list);//判断5是否在线性表中System.out.println(list.contains(5));//返回第一个5所在的下标e=list.indexOf(5);System.out.println(e);//返回最后一个5所在的下标e= list.lastIndexOf(5);System.out.println(e);//截取部分list,左闭右开List<Integer> newList=new ArrayList<>();newList=list.subList(1,3);System.out.println(newList);//将newList中的元素全部添加入list中list.addAll(newList);System.out.println(list);//清空listlist.clear();System.out.println(list);}
}

3.4 ArrayList的遍历 

ArrayList的遍历方式主要分为3种:

1.for循环搭配下标

2.foreach

3.使用迭代器

public class Test {public static void main(String[] args) {List<String> list=new ArrayList<>();list.add("hajimi");list.add("is");list.add("a");list.add("cat");//使用for循环搭配下标for(int i=0;i<list.size();i++){System.out.print(list.get(i)+" ");}System.out.println();//使用foreach遍历for(String s:list){System.out.print(s+" ");}System.out.println();//使用迭代器遍历Iterator<String> it=list.listIterator();while(it.hasNext()){System.out.print(it.next()+" ");}}
}

4.深度理解ArrayList 的扩容机制

观察原码:

int DEFAULT_CAPACITY表示默认的容量大小

Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA表示默认的空间

Object[] elementData表示存放元素的空间

 ArrayList的无参构造函数,将elementData初始化为DEFAULTCAPACITY_EMPTY_ELEMENTDATA,这是一个空数组,用于创建一个具有默认容量为 10的空ArrayList

ArrayList的add方法首先调用ensureCapacityInternal(size+1),size表示当前顺序表的有效长度,size+1表示添加元素后应有的长度 

 size+1的值传递给ensureCapacityInternal的形参minCapacity,ensureCapacityInternal先调用calculateCapacity(Object[] element,int minCapacity)传入存放元素的空间elementData和minCapacity

calculateCapacity(Object[] elementData,int minCapacity)用来计算ArrayList需要增长到的最小容量。判断elementData是否等于DEFAULTCAPACITY_EMPTY_ELEMENTDATA,如果相等则意味着ArrayList当前没有分配任何容量,是空的。在这种情况下,方法返回DEFAULT_CAPACITY(10)和minCapacity中的较大值。如果element不是空数组,则意味着ArrayList已经有了一些容量,这种情况下,直接返回minCapacity,可以保证它至少增长到minCapacity即可

 calculateCapacity的返回值传递给ensureExplicitCapacity的形参minCapacity,判断当前是否需要扩容,如果minCapacity大于数组的长度,则表示需要进行扩充

 ArrayList的扩容函数grow(int minCapacity)用于增加ArrayList的内部数组elementData的容量,使其至少容纳minCapacity个元素。

int newCapacity=oldCapacity+(oldCapacity >> 1)计算新的容量,通常是当前容量的1.5倍

if(newCapacity - minCapacity < 0)判断新容量是否满足最小的需求,如果计算出的容量仍然小于最小的容量,则将newCapacity设置为minCapacity

if(newCapacity-MAX_ARRAY_SIZE > 0)检查新容量是否超出最大数组的大小,如果超过了调用hugeCapacity处理这种情况(将新容量设为Integer.MAX_VALUES)

elementData = Arrays.copyOf(elementData,newCapacity)使用copyOf创建一个新的数组,并将就数组中的元素复制到新数组中。

总结:

1.首先判断是否需要进行扩容,如果需要进行扩容,调用grow方法

2.计算扩容所需的最小的容量

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

如果用户所需大小大于预估的1.5倍,则按照用户所需大小进行扩容

扩容前检查是否可以扩容成功,防止太大导致扩容失败

3.使用Arrays.copyOf进行扩容

5.实现一个ArrayList

package datastructure;import java.util.Arrays;public class MyArrayList {public int[] elem;public int usedSize;//0//默认容量private static final int DEFAULT_SIZE = 2;public MyArrayList() {this.elem = new int[DEFAULT_SIZE];}/*** 打印顺序表:*   根据usedSize判断即可*/public void display() {for(int i=0;i<this.usedSize;i++){System.out.print(elem[i]+" ");}System.out.println();}// 新增元素,默认在数组最后新增public void add(int data) {if(isFull()){//扩容this.elem=Arrays.copyOf(this.elem,2*this.elem.length);}this.elem[this.usedSize]=data;this.usedSize++;}/*** 判断当前的顺序表是不是满的!* true:满   false代表空*/public boolean isFull() {if(this.usedSize==this.elem.length){return true;}return false;}private boolean checkPosInAdd(int pos) {if(pos<0||pos>usedSize){System.out.println("位置不合法");return false;}return true;//合法}// 在 pos 位置新增元素//移动数据,从后向前防止数值被覆盖public void add(int pos, int data) {if(pos<0||pos>this.usedSize){System.out.println("位置不合法");return;}if(isFull()){//扩容this.elem=Arrays.copyOf(this.elem,2*this.elem.length);}for(int i=this.usedSize-1;i>=pos;i--){this.elem[i+1]=this.elem[i];}this.elem[pos]=data;usedSize++;}// 判定是否包含某个元素public boolean contains(int toFind) {for(int i=0;i<this.usedSize;i++){if(elem[i]==toFind){return true;}}return false;}// 查找某个元素对应的位置public int indexOf(int toFind) {if(isEmpty()){System.out.println("表中没有元素");return -1;}for(int i=0;i<usedSize;i++){if(elem[i]==toFind){return i;}}System.out.println("没找到");return -1;}// 获取 pos 位置的元素public int get(int pos) {if(pos<0&&pos>=usedSize){System.out.println("输入不合法!");return -1;}if(!isEmpty()){return elem[pos];}return -1;}private boolean isEmpty() {if(usedSize==0){return true;}return false;}// 给 pos 位置的元素设为【更新为】 valuepublic void set(int pos, int value) {if(pos<0||pos>=usedSize)return;elem[pos]=value;}/*** 删除第一次出现的关键字key* @param key*/public void remove(int key) {int index=indexOf(key);if(index==-1){return;}for(int i=index;i<usedSize-1;i++){this.elem[i]=this.elem[i+1];}this.usedSize--;}// 获取顺序表长度public int size() {return this.usedSize;}// 清空顺序表public void clear() {this.usedSize=0;}
}

6.ArrayList的特点

1.基于数组实现:

ArrayList使用一个动态数组来存储元素

2.动态数组容量

ArrayList可以根据添加元素的情况进行自动扩容,默认情况下是按照当前容量的1.5倍进行扩容

3.随机访问效率高,时间复杂度为O(1)

ArrayList基于数组实现,支持随机访问,时间复杂度为O(1)

4.插入和删除操作时间复杂度为O(n)

在ArrayList的中间位置插入或删除元素效率不高,这些操作会移动插入点之后的所有元素,时间复杂度为O(n),但是在末尾插入或删除元素的时间复杂度为O(1)

5.允许有重复的元素

6.允许存储null元素

7.ArrayList是线程不安全的

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

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

相关文章

C#使用WMI获取控制面板中安装的所有程序列表

C#使用WMI获取控制面板中安装的所有程序列表 WMI 全称Windows Management Instrumentation,Windows Management Instrumentation是Windows中用于提供共同的界面和对象模式以便访问有关操作系统、设备、应用程序和服务的管理信息。如果此服务被终止&#xff0c;多数基于 Windo…

CPU狂飙900%如何分析?怎么定位?怎么溯源处理

当你的服务器CPU飙升到900%&#xff0c;系统卡顿、响应迟缓、业务受阻&#xff0c;这种令人焦虑的场景是否让你束手无策&#xff1f;别慌&#xff0c;这并不是世界末日&#xff0c;只要掌握正确的分析与定位方法&#xff0c;就能快速找到问题根源&#xff0c;并有效解决。 CPU…

第五篇 vue3 ref 与 reactive 对比

ref 若需要自动加载 .value ,那么就要在 底部 菜单 中 设置 选项 选择 vue 勾选 &#xff1a; Auto Insert: Dot Value Auto-complete Ref value with .value. 注意点&#xff1a; ref 不能写越过 value. 必须要在valeu 前面 进行定义 通过 reactive 来修改整体名称…

“大模型横扫千军”背后的大数据挖掘--浅谈MapReduce

文章目录 O 背景知识1 数据挖掘2 邦费罗尼原则3 TF.IDF4 哈希函数5 分布式文件系统 一、MapReduce基本介绍1. Map 任务2. 按键分组3. Reduce 任务4. 节点失效处理5.小测验&#xff1a;在一个大型语料库上有100个map任务和若干reduce任务&#xff1a; 二、基于MapReduce的基本运…

Linux系统的第一个进程是什么?

Linux进程的生命周期从创建开始&#xff0c;直至终止&#xff0c;贯穿了一个进程的整个存在过程。我们可以通过系统调用fork()或vfork()来创建一个新的子进程&#xff0c;这标志着一个新进程的诞生。 实际上&#xff0c;Linux系统中的所有进程都是由其父进程创建的。 既然所有…

使用tritonserver完成clip-vit-large-patch14图像特征提取模型的工程化。

1、关于clip-vit-large-patch14模型 关于openapi开源的clip-vit-large-patch14模型的特征提取&#xff0c;可以参考之前的文章&#xff1a;Elasticsearch向量检索需要的数据集以及768维向量生成这篇文章详细介绍了模型的下载地址、使用方式、测试脚本&#xff0c;可以让你一步…

人工智能之深度学习_[3] -PyTorch自动微分模块和构建线性回归模型

文章目录 自动微分模块9.1 梯度基本计算9.2 梯度下降法求最优解9.3 梯度计算注意点9.4 自动微分模块应用 10 PyTorch构建线性回归模型 自动微分模块 自动微分就是自动计算梯度值,也就是计算导数。 什么是梯度 对函数求导的值就是梯度 什么是梯度下降法 是一种求最优梯度值的方法…

logback日志自定义占位符

前言 在大型系统运维中&#xff0c;很大程度上是需要依赖日志的。在java大型web工程中&#xff0c;一般都会使用slf4jlogback这一个组合来实现日志的管理。 logback中很多现成的占位符可以可以直接使用&#xff0c;比如线程号【%t】、时间【%d】、日志等级【%p】&#xff0c;…

Qt中自定义信号与槽

在学习信号和槽的时候&#xff0c;我们知道信号一般对应的就是用户的行为&#xff0c;槽指的是接受到信号后的响应&#xff0c;在类内有许多的内置信号和槽函数&#xff0c;能够去实现一些常见的行为&#xff0c;但实际业务开发中&#xff0c;尤其是接受到信号的响应会根据具体…

Yearning开源MySQL SQL审核平台

一款MYSQL SQL语句/查询审计工具&#xff0c;为DBA与开发人员使用. 本地部署&#xff0c;注重隐私&#xff0c;简单高效的MYSQL审计平台。 它可以通过流程审批&#xff0c;实现真实线上环境sql的审核和执行&#xff0c;还可以回滚执行&#xff0c;能够确保线上SQL更新的可靠性…

【Python项目】小区监控图像拼接系统

【Python项目】小区监控图像拼接系统 技术简介&#xff1a;采用Python技术、B/S框架、MYSQL数据库等实现。 系统简介&#xff1a;小区监控拼接系统&#xff0c;就是为了能够让业主或者安保人员能够在同一时间将不同地方的图像进行拼接。这样一来&#xff0c;可以很大程度的方便…

汇编与逆向(一)-汇编工具简介

RadASM是一款著名的WIN32汇编编辑器&#xff0c;支持MASM、TASM等多种汇编编译器&#xff0c;Windows界面&#xff0c;支持语法高亮&#xff0c;自带一个资源编辑器和一个调试器。 一、汇编IDE工具&#xff1a;RadASM RadASM有内置的语言包 下载地址&#xff1a;RadASM asse…

基于STM32的智能门锁安防系统(开源)

目录 项目演示 项目概述 硬件组成&#xff1a; 功能实现 1. 开锁模式 1.1 按键密码开锁 1.2 门禁卡开锁 1.3 指纹开锁 2. 功能备注 3. 硬件模块工作流程 3.1 步进电机控制 3.2 蜂鸣器提示 3.3 OLED显示 3.4 指纹与卡片管理 项目源代码分析 1. 主程序流程 (main…

AUTOSAR OS模块详解(三) Alarm

AUTOSAR OS模块详解(三) Alarm 本文主要介绍AUTOSAR OS的Alarm&#xff0c;并对基于英飞凌Aurix TC3XX系列芯片的Vector Microsar代码和配置进行部分讲解。 文章目录 AUTOSAR OS模块详解(三) Alarm1 简介2 功能介绍2.1 触发原理2.2 工作类型2.3 Alarm启动方式2.4 Alarm配置2.5…

YOLO目标检测1

一. 参考资料 《YOLO目标检测》 by 杨建华博士 二. 背景 2.1 目标检测发展简史 2014年&#xff0c;RCNN问世&#xff0c;R-CNN的思路是先使用一个搜索算法从图像中提取出若干感兴趣区域(region of interest&#xff0c;RoI)&#xff0c;然后使用一个卷积神经网络(convolutio…

【Qt 常用控件】显示类控件——QLabel

目录 1.QLabel 1.1 textFormat 文本类型 普通文本和富文本 Markdown格式 1.2 alignment 文本对齐方式 1.3 wordWrap 自动换行 1.4 indent 文本缩进 1.5 margin 边距 1.6 buddy&#xff0c;qlabel伙伴 1.7 pixmap图片 和 scaledContents自动填充 1.QLabel 功能&#x…

vif-方差膨胀因子计算

vif-方差膨胀因子 使用statsmodels中的variance_inflation_factor&#xff0c;数据集使用乳腺癌数据集 import pandas as pd import numpy as np from sklearn.datasets import load_breast_cancer from tqdm import notebook from statsmodels.stats.outliers_influence impor…

查看电脑或笔记本CPU的核心数方法及CPU详细信息

一、通过任务管理器查看 1.打开任务管理器 可以按下“Ctrl Shift Esc”组合键&#xff0c;或者按下“Ctrl Alt Delete”组合键后选择“任务管理器”来打开。 2.查看CPU信息 在任务管理器界面中&#xff0c;点击“性能”标签页&#xff0c;找到CPU使用记录区域&#xff0c…

数据恢复常见故障(四)关键信号的耦合电容撞件后导致SATA前端通信异常

数据恢复常见故障&#xff08;四&#xff09;关键信号耦合电容撞件后导致SATA前端通信异常 SATA固态硬盘SATA差分信号上有耦合电容&#xff0c;电容被撞件后&#xff0c;偏移&#xff0c;导致接触不良&#xff0c;引起SATA前端信号通信异常&#xff0c;故障现象表现为不认盘&a…

[HCTF 2018]WarmUp

题目&#xff1a;一上来给了个图片还是很懵的&#xff0c;于是尝试查看一下源代码&#xff1a;发现有提示&#xff1a;于是访问source.php得到了php代码&#xff1a;(这里将代码和代码分析放一块) <?phphighlight_file(__FILE__); class emmm{public static function chec…