数据结构入门到入土——ArrayList与顺序表

目录

一,线性表

二,顺序表

1.接口实现

三,ArrayList简介

四,ArrayList使用

1.ArrayList的构造

2.ArrayList常见操作

3.ArrayList的遍历

4.ArrayList的扩容机制

五,ArrayLisit的具体使用

杨辉三角


一,线性表

线性表 linear list n 个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

二,顺序表

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

1.接口实现

接口部分:

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();//判断顺序表是否已满public boolean isFull();//判断顺序表是否为空public boolean isEmpty();
}

接口实现:

import java.util.Arrays;public class MyArrayList implements IList{public int[] elem;public int usedSize;public static final int DEFINE_SIZE = 10;public MyArrayList() {this.elem = new int[DEFINE_SIZE];}public MyArrayList(int capacity) {this.usedSize = capacity;}@Override//新增元素,默认在数组最后新增//1.检查数组是否已满//2.满了扩容,未满新增//usedSize++public void add(int data) {if (isFull()) {elem = Arrays.copyOf(elem,2 * elem.length);}this.elem[this.usedSize] = data;this.usedSize++;}public boolean isFull() {return this.usedSize ==elem.length;}@Override//在 pos 位置新增元素//1.检查数组是否已满//2.满了扩容//3.未满:在指定位置新增,原位置有元素就向后挪//4.usedSize++public void add(int pos, int data) {if (isFull()) {elem = Arrays.copyOf(elem,2 * elem.length);}//新增int i = this.usedSize;while (i > pos) {elem[i] = elem[i-1];i--;}this.elem[pos] = data;usedSize++;}@Override// 判定是否包含某个元素//1.顺序表是否为空//2.查找元素public boolean contains(int toFind) {if (isEmpty()) {return false;}//查找元素if (findVal(toFind) != 0) {return true;}return false;}public int findVal(int val) {for (int i = 0; i < elem.length; i++) {if (elem[i] == val) {return i;}}return 0;}public boolean isEmpty() {return usedSize == 0;}@Override// 查找某个元素对应的位置// 1.判断是否为空// 2.为空抛空List异常// 3.查找元素// 4.获取下标public int indexOf(int toFind) throws EmptyListException{if (isEmpty()) {throw new EmptyListException("空List异常");}//查找if (findVal(toFind) == 0) {//查询不到异常throw new NotFindException("NotFindException");}return findVal(toFind);}@Override// 获取 pos 位置的元素// 1.判断是否为空// 2.判断pos位置是否合法// 3.获取public int get(int pos) {if (isEmpty()) {throw new EmptyListException("空List异常");}if (checkPos(pos)) {//pos位置不合法throw new PosException("pos位置不合法");}return this.elem[pos];}private boolean checkPos(int pos) {if (pos < 0 || pos >= this.usedSize) {return true;}return false;}@Override// 给 pos 位置的元素设为 value// 1.判断是否为空// 2.判断pos位置是否合法// 3.设置public void set(int pos, int value) {if (isEmpty()) {throw new EmptyListException("空List异常");}if (checkPos(pos)) {//pos位置不合法throw new PosException("pos位置不合法");}this.elem[pos] = value;}@Override// 删除第一次出现的关键字key// 是否为空?// 查找关键字public void remove(int toRemove) {if (isEmpty()) {throw new EmptyListException("空List异常");}for (int i = indexOf(toRemove);i < this.usedSize - 1;i++) {elem[i] = elem[i+1];}usedSize--;}@Override// 获取顺序表长度public int size() {return this.usedSize;}@Override// 清空顺序表public void clear() {this.usedSize = 0;}@Overridepublic void display() {System.out.print("[");if (this.usedSize == 0) {System.out.println("]");}for (int i = 0; i < this.usedSize; i++) {if (i == this.usedSize - 1) {System.out.println(this.elem[i] + "]");} else {System.out.print(this.elem[i] + ",");}}}
}

三,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 底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表

四,ArrayList使用

1.ArrayList的构

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

public static void main(String[] args) {

// ArrayList创建,推荐写法

// 构造一个空的列表

List<Integer> list1 = new ArrayList<>();

// 构造一个具有10个容量的列表

List<Integer> list2 = new ArrayList<>(10);

list2.add(1);

list2.add(2);

list2.add(3);

// list2.add("hello"); // 编译失败,List<Integer>已经限定了,list2中只能存储整形元素

// list3构造好之后,与list中的元素一致

ArrayList<Integer> list3 = new ArrayList<>(list2);

// 避免省略类型,否则:任意类型的元素都可以存放,使用时将是一场灾难

List list4 = new ArrayList();

list4.add("111");

list4.add(100);

}

2.ArrayList常见操作

ArrayList虽然提供的方法比较多,但是常用方法如下所示,需要用到其他方法时,可行查阅使用。
方法解释
boolean add (E e)
尾插e
void add (int index, E element)
将e插入到index位置
boolean addAll (Collection<? extends E> c)
尾插e中的元素
E remove (int index)
删除index位置元素
boolean remove (Object o)
删除遇到的第一个o
E get (int index)
获取下标index位置元素
E set (int index, E element)
将下标index位置元素设置成element
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

public static void main(String[] args) {

List<String> list = new ArrayList<>();

list.add("JavaSE");

list.add("JavaWeb");

list.add("JavaEE");

list.add("JVM");

list.add("测试课程");

System.out.println(list);

// 获取list中有效元素个数

System.out.println(list.size());

// 获取和设置index位置上的元素,注意index必须介于[0, size)

System.out.println(list.get(1));

list.set(1, "JavaWEB");

System.out.println(list.get(1));

// listindex位置插入指定元素,index及后续的元素统一往后搬移一个位置

list.add(1, "Java数据结构");

System.out.println(list);

// 删除指定元素,找到了就删除,该元素之后的元素统一往前搬移一个位置

list.remove("JVM");

System.out.println(list);

// 删除listindex位置上的元素,注意index不要超过list中有效元素个数,否则会抛出下标越界异常

list.remove(list.size()-1);

System.out.println(list);

// 检测list中是否包含指定元素,包含返回true,否则返回false

if(list.contains("测试课程")){

list.add("测试课程");

}

// 查找指定元素第一次出现的位置:indexOf从前往后找,lastIndexOf从后往前找

list.add("JavaSE");

System.out.println(list.indexOf("JavaSE"));

System.out.println(list.lastIndexOf("JavaSE"));

// 使用list[0, 4)之间的元素构成一个新的SubList返回,但是和ArrayList共用一个elementData数组

List<String> ret = list.subList(0, 4);

System.out.println(ret);

list.clear();

System.out.println(list.size());

}

3.ArrayList的遍历

ArrayList的遍历有三种方式:for()+下标,for-each,使用迭代器

public static void main(String[] args) {
   
List<Integer> list1 = new ArrayList<>();
   
list1.add(1);
   
list1.add(2);
   
list1.add(3);
   
list1.add(4);
   
list1.add(5);
   
//使用for()+下标遍历
   
for (int i = 0; i < list1.size(); i++) {
       
System.out.print(list1.get(i) + " ");
    }
   
System.out.println(" ");
   
//使用for-each遍历
   
for (Integer integer:list1) {
       
System.out.print(integer + " ");
    }
   
System.out.println(" ");
   
//使用迭代器遍历
   
Iterator<Integer> it = list1.iterator();
   
while (it.hasNext()) {
       
System.out.print(it.next() + " ");
    }
   
System.out.println(" ");
}

注意:
        1. ArrayList 最长使用的遍历方式是: for 循环 + 下标 以及 foreach
        2. 迭代器是设计模式的一种,后序容器接触多了再给大家铺垫

4.ArrayList的扩容机制

ArrayList是一个动态类型的顺序表,即:在插入元素的过程中会自动扩容。以下是ArrayList源码中扩容方式。

Object[] elementData; // 存放元素的空间

private static fifinal Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默认空间

private static fifinal int DEFAULT_CAPACITY = 10; // 默认容量大小

public boolean add(E e) {

ensureCapacityInternal(size + 1); // Increments modCount!!

elementData[size++] = e;

return true;

}

private void ensureCapacityInternal(int minCapacity) {

ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));

}

private static int calculateCapacity(Object[] elementData, int minCapacity) {

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

return Math.max(DEFAULT_CAPACITY, minCapacity);

}

return minCapacity;

}

private void ensureExplicitCapacity(int minCapacity) {

modCount++;

// overflflow-conscious code

if (minCapacity - elementData.length > 0)

grow(minCapacity);

}

private static fifinal int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

private void grow(int minCapacity) {

// 获取旧空间大小

int oldCapacity = elementData.length;

// 预计按照1.5倍方式扩容

int newCapacity = oldCapacity + (oldCapacity >> 1);

// 如果用户需要扩容大小 超过 原空间1.5倍,按照用户所需大小扩容

if (newCapacity - minCapacity < 0)

newCapacity = minCapacity;

// 如果需要扩容大小超过MAX_ARRAY_SIZE,重新计算容量大小

if (newCapacity - MAX_ARRAY_SIZE > 0)

newCapacity = hugeCapacity(minCapacity);

// 调用copyOf扩容

elementData = Arrays.copyOf(elementData, newCapacity);

}

private static int hugeCapacity(int minCapacity) {

// 如果minCapacity小于0,抛出OutOfMemoryError异常

if (minCapacity < 0)

throw new OutOfMemoryError();

return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;

}

总结

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

2. 预估需要库容的大小

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

•   如果用户所需大小超过预估1.5倍大小,则按照用户所需大小扩容

•   真正扩容之前检测是否能扩容成功,防止太大导致扩容失败

3. 使用copyOf进行扩容

五,ArrayLisit的具体使用

杨辉三角

class Solution {//求杨辉三角方法public List<List<Integer>> generate(int numRows) {List<List<Integer>> ret = new ArrayList<>();//二维数组List<Integer> list = new ArrayList<>();list.add(1);ret.add(list);for (int i = 1; i < numRows; i++) {List<Integer> curRow = new ArrayList<>();//当前行List<Integer> prevRow = ret.get(i-1);//上一行curRow.add(1);//当前行首个元素为1for (int j = 1; j < i; j++) {int val = prevRow.get(j-1) + prevRow.get(j);curRow.add(val);}curRow.add(1);//当前行最后一个元素为1ret.add(curRow);}return ret;}
}
public class Test {//方法使用public static void main(String[] args) {Solution solution = new Solution();List<List<Integer>> mylist = new ArrayList<>();mylist = solution.generate(3);for (int i = 0; i < 3; i++) {List<Integer> arr = mylist.get(i);System.out.println(arr);}}
}

完。

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

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

相关文章

linux 使用log4cpp记录项目日志

为什么要用log4cpp记录项目日志 在通常情况下&#xff0c;Linux/UNIX 每个程序在开始运行的时刻&#xff0c;都会打开 3 个已经打开的 stream. 分别用来输入&#xff0c;输出&#xff0c;打印错误信息。通常他们会被连接到用户终端。这 3 个句柄的类型为指向 FILE 的指针。可以…

【保研记录】2023年(24届)SE上岸经历

先开个坑&#xff0c;慢慢填~ 个人信息 学校&#xff1a;某双非 专业&#xff1a;软件工程 第四轮学科评估&#xff1a;无&#xff08;对就是没有等级&#xff09; 排名&#xff1a;1/400 竞赛/荣誉&#xff1a;国奖x2&#xff0c;省三好&#xff0c;大英国二&#xff0c;…

视频剪辑方法:一键批量转码,视频转GIF教程详解

在数字媒体时代&#xff0c;视频剪辑已经成为一项必备技能。无论是专业人士还是普通用户&#xff0c;都要对视频进行剪辑、转码和制作。但是视频剪辑并不简单&#xff0c;要掌握一定的技巧和知识。下面一起来看云炫AI智剪简单易学的视频剪辑方法&#xff1a;一键批量转码和视频…

案例093:基于微信小程序的南宁周边乡村游设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

【MATLAB】【数字信号处理】线性卷积和抽样定理

已知有限长序列&#xff1a;xk1,2,1,1,0,-3, hk[1,-1,1] , 计算离散卷积和ykxk*h(k) 。 程序如下&#xff1a; function [t,x] My_conv(x1,x2,t1,t2,dt) %文件名与函数名对应 %自写的卷积函数 x conv(x1,x2)*dt; t0 t1(1) t2(1); L length(x1) length(x2)-2; t t0:dt…

thinkphp6入门(14)-- 多关联模型查询

背景&#xff1a; 有3个数据表&#xff0c;一个User表&#xff0c;一个Cloth表&#xff0c;一个Shoe表。 Cloth表和Shoe表分别和User表通过user_id关联。 thinkphp 6中如何通过模型查询所有用户&#xff0c;其中包括每个用户的cloth和shoe。 多关联模型查询&#xff1a; 1.…

Qt6学习笔记:对象树

使用QObject及其子类创建的对象是以对象树的形式来组织的。创建一个QObject对象时若设置一个父对象&#xff0c;它就会被添加到父对象的子对象列表里&#xff0c;一个父对象被删除时&#xff0c;其全部的子对象都会自动删除。QObject类的构造函数里有一个参数用于设置对象的父对…

CommonJS 和 ES6 Module:一场模块规范的对决(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

python 数据容器

数据容器概念 一个可以存储多个元素的python数据类型 python有的数据容器 list(列表) tuple(元组) str(字符串) set(集合) dct(字典) 列表 python的列表的数据类型可以是不同的 my_list ["1",123,True,[123,"3333",d,False]]for item in my_list:p…

【uniapp】多规格选择

效果图 VUE <template> <view><view class"wp-80 pd-tb-40 mg-auto"><button type"warn" click"showDrawer(showRight)">筛选</button></view><!-- 筛选-uni-drawer --><uni-drawer ref"s…

暗光增强——Zero-DCE网络推理测试

目录 一、Zero-DCE方法1.1 网络优点1.2 网络适用场景1.3 网络不适用场景 二、源码包三、测试四、测试结果五、推理速度六、总结 一、Zero-DCE方法 Zero-DCE&#xff08;Zero-Reference Deep Curve Estimation&#xff09;是一种用于低光照增强的网络。 1.1 网络优点 无需参考…

ClickHouse数据库详解和应用实践

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 概述1.适用场景2.不适用场景 一、核心特性1.完备的DBMS功能2.列式存储与数据压缩 二、安装部署1.在线安装2.离线安装 三、jdbc访问总结 概述 ClickHouse 是一个用于…

wordpress在界面将站点地址直接修改为https导致上不去问题的解决办法

wordpress在界面将站点地址直接修改为https导致上不去问题的解决办法 #修改数据库yz_options

计算机网络——OSI参考模型

1. OSI模型的基本概念 1.1 定义 OSI&#xff08;开放式系统互联&#xff09;模型是一个用于理解和标准化电信系统或计算机网络功能的概念性的框架&#xff0c;用于描述和标准化不同计算机系统或网络设备间通信的功能。 1.2 OSI模型的性质 这个模型由国际标准化组织&#xff08…

StartAI 生图关键词整理 第一期

最近很多小伙伴向小编反馈“StartAI生图效果很差”&#xff0c;“效果不好”...... AI生图的关键在于是否投喂合适的关键词。往往好的创意需要好的词汇去润色~ 小编立刻决定给小伙伴们整理生图关键词&#xff01;&#xff01;&#xff01;&#xff01; 一、生成菠萝的创意切面…

数据结构之哈希——学习笔记

今天看网课学习了哈希的数据结构&#xff0c;写下这一篇博客记录自己的学习过程。 1.哈希简介&#xff1a; 我们发现某些时候映射到小集合的时候会同时有多个值映射到一个下标里面&#xff0c;所以接下来是这种情况的解决方案1&#xff1a; 我们考虑当两个数字映射之后的结果…

FastDFS

docker 安装 1拉取镜像&#xff08;已经内置Nginx&#xff09; docker pull delron/fastdfs 2 构建Tracker # 22122 > Tracker默认端口 docker run --nametracker-server --privilegedtrue -p 22122:22122 -v /var/fdfs/tracker:/var/fdfs -d delron/fastdfs tracker 3 …

【ESP32接入语言大模型之通义千问】

1. 通义千问 讲解视频&#xff1a; ESP32接入语言大模型之通义千问 随着人工智能技术的不断发展&#xff0c;自然语言处理领域也得到了广泛的关注和应用。通义千问由阿里云开发&#xff0c;目标是帮助用户获得准确、有用的信息&#xff0c;解决他们的问题和困惑&#xff0c;也…

数据库 补充 树,红黑树,b树,b+树

01.树 02.二叉树和二叉平衡树 03.平衡二叉树的恢复 将导致不平衡的结点称作被破坏者&#xff0c;破坏了结点的平衡的结点成为破坏者&#xff0c;经过调整可以让该树平衡的结点称为调整结点。 LL型&#xff1a; 以被破坏者的左孩子结点作为调整结点&#xff0c;对其进行右旋…

C# Attribute特性实战(1):Swtich判断优化

文章目录 前言简单Switch问题无参Swtich方法声明Swtich Attribute声明带有Swtich特性方法主方法结果 有参Switch修改代码修改运行过程运行结果 总结 前言 在经过前面两章内容的讲解&#xff0c;我们已经简单了解了如何使用特性和反射。我们这里解决一个简单的案例 C#高级语法 …