数据结构 线性结构篇——动态数组和时间复杂度分析(1)

简介: 数据结构 线性结构篇——动态数组和时间复杂度分析

一、数组基础

1.1 定义

  • 数组(Array)是一种线性表数据结构,它用一组连续的内存空间来存储一组具有相同类型的数据。

1.2 创建流程

  • 当我们在 java 中当创建一个数组时,会在内存中划分出一块 连续的内存 ,当有数据进入的时候会将数据 按顺序 的存储在这块连续的内存中。当需要读取数组中的数据时,需要提供数组中的 索引 ,然后数组根据索引将内存中的数据取出来,返回给读取程序。

把数据码成一排进行存放:image.png所有的数据结构都支持几个基本操作:读取、插入、删除


数组索引可以有语意,也可以没有语意,比如说 student[2],就代表是这个数组中的第三个学生。


因为数组在存储数据时是按顺序存储的,存储数据的内存也是连续的,所以数组最大的优点就是能够 快速查询 ,寻址读取数据比较容易,但是插入和删除就比较困难。


为什么数组最大的优点就是能够 快速查询 。因为当我们在读取数据时,只需要告诉数组获取数据的索引位置就可以了,数组就会把对应位置的数据,读取出来


插入 和 删除 比较困难是因为这些存储数据的内存是连续的,数组大小固定,插入和删除都需要移动元素


image.png


例如:一个数组中编号 0 > 1 > 2 > 3 > 4这五个内存地址中都存了数组的数据,但现在你需要往4中插入一个数据,那就代表着从4开始,后面的所有内存中的数据都要往后移一个位置。


二、编写我们自己的数组类


我们知道想要维护某一个数据,我们需要对这个数据有这最基本的增、删、改、查,这几个基本功能,所以我们自己手动编写的数组类,也是需要有用这几个最基本的功能,虽然不会像List、Map这些类,那么强大,但是对于我们普通的开发来说,基本是可以满足,下图所示就是我们一个基本的数组类,那么我们是如何对数组进行改造,来编写一个属于我们自己的数组类的呢,这里我们以 增加和删除做重点讲解 ,本文中的所有源码会在最后贴出来,请往下看。


image.png

从上图中我们可以得知,我们创建数组类的时候,需要三个元素 data、size、capacity,而我们所需要使用的数组,肯定是要能够支持 多种数据类型 ,而不是单一的数据结构,因此,我们可以在设计类的时候,是需要加上泛型支持,让我们的数据结构可以支持放置 “任何” 数据类型。


data:需要传递的数据

size:元素中的个数

capacity:数组的初始容量


注意:我们上面所说的放置 “任何” 数据类型,只能是类对象,不可以是基本数据类型,但是我们每个基本数据类型都有对应的包装类,所以我们的基本类型也是可以使用的,不过只是使用的是它的包装类

屏幕快照 2022-05-10 下午2.21.35.png

/**
 * @program: 
 * @ClassName ArrayPlus
 * @description:
 * @author: lyy
 * @create: 2019-11-18 22:27
 * @Version 1.0
 **/
public class ArrayPlus<E> {
    private E[] data;
    private int size;
    //构造函数,传入数组的容量capacity 构造array
    public ArrayPlus(int capacity){
        data = (E[])new Object[capacity];
        size = 0;
    }
    //无参数的构造函数,传入数组的容量capacity=10
    public ArrayPlus(){
        this(10);
    }
    //获取元素中的个数
    public int getSize(){
        return size;
    }
    //获取数组的容量
    public int getCapacity(){
        return data.length;
    }
    //返回数组是否为空
    public boolean isEmpty(){
        return size == 0;
    }
    @Override
    public String toString(){
        StringBuffer res = new StringBuffer();
        res.append(String.format("Array:Size = %d,capacity = %d\n",size,data.length));
        res.append("[");
        for (int i = 0; i < size; i++) {
            res.append(data[i]);
            if(i != size - 1)
                res.append(",");
        }
        res.append("]");
        return res.toString();
    }
}

2.1 数组添加元素


在数组中是如何添加数据的呢,首先我们需要创建一个 拥有初始容量 的数组,当我们创建完成之后,size 是指向第一个元素的,也就是 index = 0的地方,当我们添加第一个数据后 也就是 data[0] = 12后,我们的元素中的个数 size,需要往后挪一位的,也就是 size++ 的操作,每当我们操作一位,就需要将上面的操作重复执行,直到最后一个元素添加到我们的数组中。

image.png

知道了怎么操作,但是我们要如果通过代码来完成呢?


首先我们要清楚在添加的时候, 在哪里?添加什么数据?,在哪里:我们要在数据的什么地方进行添加,也就是要添加到数组中的哪个下标—— index 的地方,知道了在下标,我们只需要将添加的数据,添加到数组中为 index 的地方即可,除此之外,我们只需要对添加时,做一些基本的判断就可以了,代码如下:

   //在所有元素后添加一个新元素
    public void addLast(E e){
        add(size,e);
    }
    //想所有元素前添加一个新元素
    public void addFirst(E e){
        add(0,e);
    }
    //在第Index个位置插入一个新元素e
    public void add(int index,E e){
        if(size == data.length)
            throw new IllegalArgumentException("Add failed . Array is full.");
        if(index < 0 || index > size)
            throw new IllegalArgumentException("Add failed . Require index < 0 || index > size.");
        for (int i = size - 1; i >= index ; i--)
            data[i+1] = data[i];
        data[index]  = e;
        size++;
    }

测试代码:


public class Main2 {
    public static void main(String[] args) {
        ArrayPlus<Integer> arr = new ArrayPlus<>();
        for (int i = 12; i < 16; i++)
            arr.addLast(i);
        System.out.println(arr);
    }
}


返回结果:


Array:Size = 4,capacity = 10
[12,13,14,15]
目录
相关文章
|
4天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
43 16
|
27天前
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
20 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
|
2月前
|
存储 Java
java数据结构,线性表链式存储(单链表)的实现
文章讲解了单链表的基本概念和Java实现,包括头指针、尾节点和节点结构。提供了实现代码,包括数据结构、接口定义和具体实现类。通过测试代码演示了单链表的基本操作,如添加、删除、更新和查找元素,并总结了操作的时间复杂度。
java数据结构,线性表链式存储(单链表)的实现
|
1月前
|
存储 编译器 C++
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析
|
2月前
|
机器学习/深度学习 算法 Java
[算法与数据结构] 谈谈线性查找法~
该文章详细介绍了线性查找法的基本概念与实现方法,通过Java代码示例解释了如何在一个数组中查找特定元素,并分析了该算法的时间复杂度。
|
22天前
|
算法
[数据结构] -- 时间复杂度和空间复杂度
[数据结构] -- 时间复杂度和空间复杂度
13 0
|
27天前
探索顺序结构:栈的实现方式
探索顺序结构:栈的实现方式
|
1月前
|
存储 算法
【数据结构】二叉树——顺序结构——堆及其实现
【数据结构】二叉树——顺序结构——堆及其实现
|
2月前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
2月前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。