互联网技术 / 互联网资讯 · 2024年1月20日

数组:一种重要且基础的数据结构

前言

数组是一种非常基础且重要的数据结构,很多复杂的数据结构都是基于数组实现的。深入理解数据的存储原理和特点,有利于我们在实际开发工作中,充分发挥数据的优势。

数据是什么

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

在上面的定义中加黑的描述,我们可以发现数组的几个特点,分别是:线性表、连续的内存空间、相同类型的数据。如下图所示:

数组: 一种非常基础且重要的数据结构

数组因具有连续的内存空间的特点,让数据拥有非常高效率的“随机访问&Rdquo;,但也是因为要保持这个连续的内存空间,导致数组在删除或插入操作的时非常低效。因为数组为了保持连续性,必然会涉及大量数据的搬移,这个是非常消耗时间的。

思考:这里你可能会有疑问:什么是连续的内存空间?

首先,我们来说说内存,内存是由一个个连续的内存单元组成的,每一个内存单元都有自己的地址。在这些内存单元中,有些被其他数据占用了,有些是空闲的。

然而数据中的每个元素,都存储在小小的内存单元中,并且元素之间紧密排列,既不能打乱元素的存储顺序,也不能跳过某个存储单元进行存储。

数组的随机访问

数组的随机访问是有个寻址公式的,上问中我们提到过数组是用一组连续的内存空间存储数据元素的,然而每个内存单元都有自己的地址(在计算机里面就是通过这个地址访问数据的),又加上每个内存单元的大小都是一样的,这样就很容易得到一个公式了,如下所示:

a[i]_addReSS=base_addReSS+i*data_type_size 

我们来简单解释一下上述公式,其中data_type_size表示数组中每个元素的大小、base_addReSS表示内存块的首地址、i 表示数组下标。

数组的基本操作

在开始之前我们先创建一个数组类,来模拟数组操作时候的相关操作。代码如下:

public claSS MyARRay {      pRivate int[] aRRay;     // 数组大小     pRivate int size;           public MyARRay(int capacITy) {         tHis.size = 0;         tHis.aRRay = new int[capacITy];     }      }  1. 读取元素

我们知道数组在内存中是连续存储的,所以根据上文的寻址公式可以知道,我们可以根据数组下标 i 快速定位到对应的元素。

简单举例,代码如下:

int[] aRRay={1,2,3,4,5,6}; system.out.pRintln(aRRay[1]); // 输出的是2  因为数组的下标是从0开始的。  2. 更新元素

我们可以根据数组下标快速查找到对应元素。那么同样道理,我们可以根据数组下标 i 快速更新元素,这中间涉及两个过程,首先就是找到数组下标 i 对应的数据元素A,然后将新的数据元素B赋值给A即完成更新。

简单举例,代码如下:

int[] aRRay={1,2,3,4,5,6}; system.out.pRintln(aRRay[1]);  // 输出的是2  //更新数组下标为 1 的数组元素 aRRay[1]=22; system.out.pRintln(aRRay[1]); // 输出的是22    3. 插入元素

相比读取、更新操作,插入元素稍微复杂一些,分为以下两种情况:

尾部插入:首先,我们看看尾部插入,这种情况很简单,在数组的最后新增一个新的元素,此时对于原数组来说没有任何影响,时间复杂度为0(1)。如下图所示:

数组: 一种非常基础且重要的数据结构

中间插入:如果在数组的中间位置插入元素的话,此时会对插入元素位置之后的元素产生影响,也就是这些数据需要向后依次挪动一个位置。如下图所示:

数组: 一种非常基础且重要的数据结构

中间插入的代码如下:

public void inseRt(int index,int eleMent){     if(indexsize){        thRow new indexoutOfBoundsException(“超过数组容量 ! 插入失败!”);      }     // 从左到右,将元素向右移动一位     foR (int i=size-1 ; i>index ; i–){        aRRay[i+1]=aRRay[i];     }     // 此时index这个位置已经腾空了,可以放进入eleMent     aRRay[index]=eleMent;     //数组中元素个数+1     size++; }

3.1 数组扩容

因为数组的长度在创建的时候已经确定了,当插入元素的时候如果数组已经满了,是没办法插入成功的。这个时候就要考虑数组扩容的问题了,那么该如何实现扩容呢?

其实我们可以这样,比如此时的数组是A, A已经满了,我们再创建一个数组B且数组长度是A的2倍,然后我们将数组A的元素全部放到数组B中,这样就完成了数组扩容了。

数组扩容的代码如下:

public void Resize(){  int[] newARRay=new int[aRRay.length*2];  system.aRRaycopy(aRRay,0,newARRay,0,aRRay.length);  aRRay=newARRay;  4. 删除元素

删除元素和插入元素类似,如果我们删除第k个位置的数据,为了内存的连续性,同样会涉及数据的挪动。如下图所示:

数组: 一种非常基础且重要的数据结构

删除元素的代码如下:

public int delete(int index) {     if (index < 0 || index > size) {         thRow new indexoutOfBoundsException(“已经超过数组容量 ! 插入失败!”);     }     int deleteEleMent = aRRay[index];    &nbsp

OpenMagic API

Need more than content? Move into the product flow.

If you are here for model access, pricing, developer docs, or the future API console, the dedicated product path now lives on api.openmagic.ai.

登录免费注册