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

news2024/12/24 2:21:22

目录

一,线性表

二,顺序表

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 位置的元素设为 value
    public void set(int pos, int value);
    //删除第一次出现的关键字key
    public 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;
    }

    @Override
    public 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);//当前行首个元素为1
            for (int j = 1; j < i; j++) {
                int val = prevRow.get(j-1) + prevRow.get(j);
                curRow.add(val);
            }
            curRow.add(1);//当前行最后一个元素为1
            ret.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.coloradmin.cn/o/1343781.html

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

相关文章

SONiC和ONL所依赖的Debian版本说明

Debian 的最新几个版本 下一代 Debian 正式发行版的代号为 trixie — 测试&#xff08;testing&#xff09;版 Debian 12 (bookworm) — 当前的稳定&#xff08;stable&#xff09;版 Debian 11 (bullseye) — 当前的旧的稳定&#xff08;oldstable&#xff09;版 Debian 10&a…

CentOS7 系统安装

系统下载 官方下载 清华源下载 安装流程 1. 选择安装系统 2. 选择安装语言 3. 设置网络链接 4. 设置静态IP ![img](https://img-blog.csdnimg.cn/img_convert/53bfedd54b838f95bd8bcb2efa232e23.png)设置时区 5. 磁盘设置&#xff0c;无特殊需求默认就好 6. 安装模式选择 7…

jwt 介绍

目录 1&#xff0c;jwt 的出现问题 2&#xff0c;jwt 介绍3&#xff0c;jwt 令牌的组成3.1&#xff0c;header3.2&#xff0c;payload3.3&#xff0c;signature 4&#xff0c;验证5&#xff0c;总结 身份验证相关内容&#xff1a; 浏览器 cookie 的原理&#xff08;详&#xff…

计算机视觉技术-锚框

目标检测算法通常会在输入图像中采样大量的区域&#xff0c;然后判断这些区域中是否包含我们感兴趣的目标&#xff0c;并调整区域边界从而更准确地预测目标的真实边界框&#xff08;ground-truth bounding box&#xff09;。 不同的模型使用的区域采样方法可能不同。 这里我们介…

蓝牙物联网移动硬件数据传输系统解决方案

随着传感器技术、网络技术和数据传输技术的不断发展&#xff0c;人们对智能设备的需求日渐增强,利用传感器技术可以对周围环境进行准确和全面的感知&#xff0c;获取到实时信息&#xff0c;从而在网络中进行传输和共享&#xff0c;再通过服务器对各种数据进行保存、分析和挖掘等…

Transformer(seq2seq、self-attention)学习笔记

在self-attention 基础上记录一篇Transformer学习笔记 Transformer的网络结构EncoderDecoder 模型训练与评估 Transformer的网络结构 Transformer是一种seq2seq 模型。输入一个序列&#xff0c;经过encoder、decoder输出结果也是一个序列&#xff0c;输出序列的长度由模型决定…

乡村北斗预警预报应急通信调度方案

根据《中共中央国务院关于切实加强农业基础建设进一步促进农业发展农民增收的若干意见》&#xff08;中发[2008]1号&#xff09;等文件要求&#xff0c;要健全农业气象服务体系和农村气象灾害防御体系&#xff0c;充分发挥气象服务“三农”的重要作用。 随着中国北斗导航卫星系…

Spark应用程序的结构与驱动程序

Apache Spark是一个强大的分布式计算框架&#xff0c;用于处理大规模数据。了解Spark应用程序的结构和驱动程序是构建高效应用的关键。本文将深入探讨Spark应用程序的组成部分&#xff0c;以及如何编写一个Spark驱动程序来处理数据和执行计算。 Spark应用程序的结构 Spark应用…

CDN:内容分发的高速公路(上)

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

如何拍摄好VR全景图片,VR全景图片后期处理有什么技巧

引言&#xff1a; VR全景图片是一种以全景视角呈现场景的图片&#xff0c;通过VR技术可以将用户带入虚拟的环境中&#xff0c;给人一种身临其境的感觉&#xff0c;那么如何才能更好的制作让人满意的全景图片呢&#xff1f; 一&#xff0e;如何拍摄好VR全景图片 1.选择合适的拍…

Java虚拟机中的垃圾回收

2 垃圾回收 2.1 判断一个对象是否可回收 2.1.1 引用计数法 如果一个对象被另一个对象引用&#xff0c;那么它的引用计数加一&#xff0c;如果那个对象不再引用它了&#xff0c;那么引用计数减一。当引用计数为 0 时&#xff0c;该对象就应该被垃圾回收了。 但是下面这种互相…

Linux自己的应用商店yum

&#x1f4ab;Linux系统如何安装软件 在Linux系统中我们可以通过多种方式安装软件&#xff0c;常见方式有以下三种&#xff1a;   1.源代码安装   2.rpm包安装   3.使用yum软件包管理器安装   早期人们通过下载软件源代码&#xff0c;然后再经过交叉编译等一系列工作下…

Vue学习day_03

普通组件的注册 局部注册: 创建一个components的文件夹 在里面写上对应的.vue文件 在对应的vue里面写上对应的3部分 template写上对应的核心代码 盒子等 style 写上对应的css修饰 在App.vue里面进行引用 import 导包 格式是 import 起个名字 from 位置 在写一个component…

【连接池】-从源码到适配(下),使用dynamic-datasource导致连接池没生效(升级版本)

写在前面 书接上文&#xff0c;连接池没生效&#xff0c;启用了一个什么默认的连接池。具体是什么&#xff0c;一起来看看源码吧。 目录 写在前面一、问题描述二、本地调试三、升级dynamic-datasource四、新的问题&#xff08;一&#xff09;数据源初始化问题&#xff08;二&am…

mysql树查询和时间段查询

本文目录 文章目录 案例1&#xff1a;MySQL树形结构查询案例2&#xff1a;MySQL查询一段时间内的所有日期 摘要 案例1&#xff1a;MySQL树形结构查询 在页面开发过程中&#xff0c;如图一所示的树形控件很常见&#xff0c;而大多数情况下&#xff0c;树形控件中需要显示的数据…

AI赋能金融创新:技术驱动的未来金融革命

人工智能&#xff08;AI&#xff09;作为一种技术手段&#xff0c;正逐渐改变金融行业的方方面面。从风险管理到客户体验&#xff0c;从交易执行到反欺诈&#xff0c;AI带来了许多创新和机遇。本文将探讨AI在金融领域的应用和其赋能的金融创新。 金融领域一直以来都面临着复杂的…

钡铼技术集IO数据采集可编程逻辑控制PLC无线4G环保物联网关

背景 数据采集传输对于环保企业进行分析和决策是十分重要的&#xff0c;而实时数据采集更能提升环保生产的执行力度&#xff0c;从而采取到更加及时高效的措施。因此实时数据采集RTU成为环保企业的必备产品之一。 产品介绍 在推进环保行业物联网升级过程中&#xff0c;环保RTU在…

Spark作业的调度与执行流程

Apache Spark是一个分布式计算框架&#xff0c;用于处理大规模数据。了解Spark作业的调度与执行流程是构建高效分布式应用程序的关键。本文将深入探讨Spark作业的组成部分、调度过程以及执行流程&#xff0c;并提供丰富的示例代码来帮助大家更好地理解这些概念。 Spark作业的组…

C语言编程入门 – 编写第一个Hello, world程序

C语言编程入门 – 编写第一个Hello, world程序 C Programming Entry - Write the first application called “Hello, world!” By JacksonML C语言编程很容易&#xff01; 本文开始&#xff0c;将带领你走过C语言编程之旅&#xff0c;通过实例使你对她颇感兴趣&#xff0c;一…

数据库一般会采取什么样的优化方法?

数据库一般会采取什么样的优化方法&#xff1f; 1、选取适合的字段属性 为了获取更好的性能&#xff0c;可以将表中的字段宽度设得尽可能小。 尽量把字段设置成not null 执行查询的时候&#xff0c;数据库不用去比较null值。 对某些省份或者性别字段&#xff0c;将他们定义为e…