2. 数组
2.1 数组的结构
数组,是一块连续的内存区域,且具有相同类型的数据结构。
说回上一次的图。(图片修改自极客专栏:《数据结构与算法之美》)
这就是数组的一块内存区域。
我们提下上面说的两个特点:
- 连续内存区域
- 相同的数据类型
这两个特点有什么好处呢?
我们上次说到,如果我们想要查找一个房间1036(一块数据),我们站在上图中1000的位置,然后有下面两种方式:
- 从1000走4步,到1004,然后再走4步,到1008,以此类推,最终走到1036(为什么每次都走4步呢,就是由相同的数据类型决定的,数据决定了数据所占空间的大小)
- 或者我们站在1000处,我们需要到a[9]处,我们在心中估算从1000应该跳多远。我们估算出4步的大概距离,然后计算(9-0)*4+1000=1036,也就是我们需要跳过9个4步的距离就可以达到目的地。
回归到计算机,我们创建一个数组:
int[] a = new int[10];
如上图所示,有10块区域,我们知道房间是连续的,我们的起始位置是1000,每个区域占4个大小,请问最后一块区域的起始地址是多少?
- 如果以0开始记号,也就是10块区域,分别记号为(0,1,...,9),可以这样计算
最后的地址 = 1000 + i * 4
- 如果以1开始记号,也就是10块区域,分别记号为(1,2,...,9, 10),可以这样计算
最后的地址 = 1000 + (i-1) * 4
所以计算机会采用0作为下标的开始。方便,快捷。
总而言之,我们如果要到达数组的某一块区域,只要算一算,然后眺一步就可以达到。
所以我们说,数组可以随机读取。
四大操作:增
往数组中增加(增加)数据。
上图中,有个数组,其中包含五个元素。我们现在想往其中添加 6 这个元素,插入到 2 元素之后。
我们应该去如何实现呢?
因为一开始的时候,数组的大小是确定的,就是五个元素。就好比一个公寓只有5个屋子,如果想再加一个房间,是不可能的。
只能重新建个6个屋子的公寓,然后让原来五个屋子中的元素搬进去,然后将 6 放入到指定屋子。
建立5个元素的数组。
int[] a = new int[5];
a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4; a[4] = 5;
实现添加元素操作
//创建一个比之前容量更大的数组
int[] new_a = new int[6];
//将添加位置前的元素拷贝到新的数组中
for(int i = 0; i < 2; i++)
new_a[i] = a[i];
//将添加位置后的元素拷贝到新的数组中
for(int i = 3; i < new_a.length; i++)
new_a[i] = a[i-1];
//将添加元素放到新数组指定位置上
new_a[2] = 6;
//给新公寓起原来公寓的名字
a = new_a;
四大操作:删除
删除操作,同添加操作类似,创建一个更小的数组,然后将不需要删除的元素拷贝进去。
四大操作:改
因为修改元素,并不修改数组的大小,所以我们无需去创建一个新的数组,只需要在指定位置直接修改即可。
a[i] = k; // 修改k位置上的数值为k
四大操作:查
这里的查询,暂时指找到特定位置的元素。前面说到,数组是连续的,所以我们只需要用数组的下标索引即可。
a[i]
总结
数组是连续的内存区域,所以只要知道元素的位置索引,我们就可以直接获得相应位置的数据。所以称:数组支持随机访问。
数组的增加、删除很麻烦,但是修改、查找指定位置很容易。
相关小练习
LeetCode基础练习,简单看下即可
Github地址 欢迎 star 收藏
寻找有趣或更有效率的事、工具和教程