数据结构之ArrayList与顺序表(有源码剖析)(一)

简介: 数据结构之ArrayList与顺序表(有源码剖析)(一)

💕"世事犹如书籍,一页页被翻过去。人要向前看,少翻历史旧账。"💕

作者:Mylvzi

文章主要内容:数据结构之顺序表的模拟实现

一.线性表

1.概念

线性表(liner list)是n个具有相同特性元素的有限序列的集合

相同特性指的是一个线性表内部存储的数据类型要都是相同的,可以都是Integer,String也可以是其他的引用类型

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

2.性质

 线性表最大特点在于他是一种连续存储数据的结构,其在逻辑上一定是连续的,但是物理上不一定连续,主要是因为线性表既可以通过数组表示,又可以通过链表实现

二.顺序表(ArrayList)

1.概念:

 顺序表是使用物理地址连续的内存存储数据的线性表

2.接口实现

ArrayList中有很多内置的接口,不过这里我们先模拟实现一下

1.顺序表的结构

顺序表最大的特点是它使用"物理地址连续"的内存进行数据的存储,在我们学习过的知识中,数组的存储刚好满足顺序表的特点

// 结构
    public int[] elem;// 使用数组来存储数据
    public int usedsize;// 有效数据个数
    // 初始化顺序表
    // 默认大小
    public static final int DEFAULT_SIZE = 10;
    public MyArrayList() {
        this.elem = new int[DEFAULT_SIZE];
    }
    // 用户指定数组大小
    public MyArrayList(int initCapacity) {
        this.elem = new int[initCapacity];
    }

2.顺序表的添加

 顺序表的添加就是在顺序表中新增一个数据,但是插入的位置要分类讨论,大致上可分为两类:

  • 默认插入:在 顺序表的末尾进行数据的插入
  • 在指定位置进行插入
1.默认插入

 注意在插入数据这样的操作中,要考虑你要插入的容器的容量是否达到最大值,如果达到最大值需要进行扩容,否则就会发生越界访问

// 默认插入
    public void add(int data) {
        // 插入之前要先检查是否需要扩容
        if(isFull()) {
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }
        // 插入
        this.elem[usedsize] = data;
        this.usedsize++;
    }
    public boolean isFull() {
        // 如果有效的数据个数和数组的长度一致  扩容
        return this.elem.length == usedsize;
    }
2.在指定位置插入数据

要在指定位置插入数据需要考虑的是原有的位置已经存在数据了,要想插入新的数据,就要将插入位置之后的所有元素都往后挪动

图解:

代码实现:

// 在指定位置进行插入
    public void addPos(int pos,int data) {
        // 检查pos是否合法
        if(pos < 0 || pos > this.usedsize) {
            throw new posOutOfBoundException(pos + "位置不合法");
        }
        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;
        this.usedsize++;
    }

注意:在pos位置插入数据的时候要检查pos是否合法,即不能产生越界访问

3.判断顺序表中是否包含某个元素

 遍历顺序表,包含返回true;不包含,返回false

代码实现:

public boolean contains(int key) {
        for (int i = 0; i < this.usedsize; i++) {
            if (this.elem[i] == key) {
                return true;
            }
        }
        // 没找到
        return false;
    }

4.查找某个元素对应的位置

如果数组包含某个元素,则返回其对应的下标

代码实现:

 

public int indexOf(int key) {
        for (int i = 0; i < this.usedsize; i++) {
            if (this.elem[i] == key) {
                return i;
            }
        }
        System.out.println("数组不包含该元素");
        return -1;
    }

5.获取pos位置的元素

返回pos位置对应的元素

代码实现

public int get(int pos) {
        // 检查pos 的位置是否合法
        if(pos < 0 || pos >= this.usedsize) {
            throw new posOutOfBoundException(pos + "位置不合法");
        }
        return this.elem[pos];
    }

注意:此处要检查pos是否合法,这里的pos最大只能访问到usedSize-1的元素

6.给pos位置的元素设置为value

即更新pos位置的元素

代码实现

public void set(int pos,int value) {
        // 检查pos 的位置是否合法
        if(pos < 0 || pos >= this.usedsize) {
            throw new posOutOfBoundException(pos + "位置不合法");
        }
        this.elem[pos] = value;
    }

7.删除第一次出现的关键字key

遍历顺序表,找到值等于key的元素,删除他(只删除第一次出现的key)

但是该则么删除呢?将要删除的元素设置为0?这显然是行不通的,可以采用"数据覆盖"来进行数据的删除,即应该先找到要删除元素的位置,在从后往前进行数据的覆盖

图解

代码实现

public void remove(int key) {
        // 1.获取key的pos
        int pos = indexOf(key);
        if (pos == -1) {
            System.out.println("没有你要删除的数据!");
            return;
        }
        // 2.挪动数据 进行删除    注意范围
        for (int i = pos; i < this.usedsize-1; i++) {
            this.elem[i] = this.elem[i+1];
        }
        this.usedsize--;
    }

8.获取顺序表的长度

代码实现

public int size() {
        return this.usedsize;
    }

9.清空顺序表

代码实现

// 清空顺序表
    public void clear() {
        // 如果是引用类型 要一一置空
//        for (int i = 0; i < this.usedsize; i++) {
//            this.elem[i] = null;
//        }
        this.usedsize = 0;
    }

10.自定义异常

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 绿字
 */
public class posOutOfBoundException extends RuntimeException{
    public posOutOfBoundException() {
    }
    public posOutOfBoundException(String message) {
        super(message);
    }
}

三.ArrayList简介

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

源码:


数据结构之ArrayList与顺序表(有源码剖析)(二)+https://developer.aliyun.com/article/1413529

目录
相关文章
|
11月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
892 9
|
4月前
|
存储 安全 Java
Java 集合面试题从数据结构到 HashMap 源码剖析详解及长尾考点梳理
本文深入解析Java集合框架,涵盖基础概念、常见集合类型及HashMap的底层数据结构与源码实现。从Collection、Map到Iterator接口,逐一剖析其特性与应用场景。重点解读HashMap在JDK1.7与1.8中的数据结构演变,包括数组+链表+红黑树优化,以及put方法和扩容机制的实现细节。结合订单管理与用户权限管理等实际案例,展示集合框架的应用价值,助你全面掌握相关知识,轻松应对面试与开发需求。
200 3
|
7月前
|
存储 自然语言处理 数据库
【数据结构进阶】AVL树深度剖析 + 实现(附源码)
在深入探讨了AVL树的原理和实现后,我们不难发现,这种数据结构不仅优雅地解决了传统二叉搜索树可能面临的性能退化问题,还通过其独特的平衡机制,确保了在任何情况下都能提供稳定且高效的查找、插入和删除操作。
520 19
|
7月前
|
数据库 C++
【数据结构进阶】红黑树超详解 + 实现(附源码)
本文深入探讨了红黑树的实现原理与特性。红黑树是一种自平衡二叉搜索树,通过节点着色(红/黑)和特定规则,确保树的高度接近平衡,从而实现高效的插入、删除和查找操作。相比AVL树,红黑树允许一定程度的不平衡,减少了旋转调整次数,提升了动态操作性能。文章详细解析了红黑树的性质、插入时的平衡调整(变色与旋转)、查找逻辑以及合法性检查,并提供了完整的C++代码实现。红黑树在操作系统和数据库中广泛应用,其设计兼顾效率与复杂性的平衡。
1101 3
|
9月前
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】顺序表的基本运算(头歌实践教学平台习题)【合集】
本文档介绍了线性表的基本运算任务,涵盖顺序表和链表的初始化、销毁、判定是否为空、求长度、输出、查找元素、插入和删除元素等内容。通过C++代码示例详细展示了每一步骤的具体实现方法,并提供了测试说明和通关代码。 主要内容包括: - **任务描述**:实现顺序表的基本运算。 - **相关知识**:介绍线性表的基本概念及操作,如初始化、销毁、判定是否为空表等。 - **具体操作**:详述顺序表和链表的初始化、求长度、输出、查找、插入和删除元素的方法,并附有代码示例。 - **测试说明**:提供测试输入和预期输出,确保代码正确性。 - **通关代码**:给出完整的C++代码实现,帮助完成任务。 文档
197 5
|
10月前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
11月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
402 16
|
11月前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
696 8
|
11月前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
11月前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
860 4