数组理论基础

数组在内存中的存储方式

数组是存放在连续内存空间上的相同类型数据的集合。

数组可以方便的通过下标索引的方式取到下标对应的数据。

如图所示:

算法通关数组

需注意两点:

  • 数组下标都是从0开始的
  • 数组内存空间的地址是连续的。
正因为数组在内存空间的地址是连续的,所以我们在删除或者插入元素时,需要移动其他元素的地址。

例如删除下标为3的元素,需要对下标为3的元素后面的所有元素做移动操作,如图所示:

算法通关数组1

且当使用C++时,需要注意 vector 和 array 的区别,vector 的底层实现是 array,严格来讲 vector 是容器,不是数组。

数组元素时不能删除的,只能覆盖。

二维数组请看图

算法通关数组2

二维数组在内的空间地址是连续的吗?

不同编程语言的内存管理是不一样的,以C++为例,在C++中 二维数组是连续分布的。

以一个实验例子为证,C++测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
void test_arr() {
int array[2][3] = {
{0, 1, 2},
{3, 4, 5}
};
cout << &array[0][0] << " " << &array[0][1] << " " << &array[0][2] << endl;
cout << &array[1][0] << " " << &array[1][1] << " " << &array[1][2] << endl;
}

int main() {
test_arr();
}

测试结果的地址为:

1
2
0x7ffee4065820 0x7ffee4065824 0x7ffee4065828
0x7ffee406582c 0x7ffee4065830 0x7ffee4065834

注意地址为16进制,可以看出二维数组地址是连续的。

因为是一个int数组,所以两个相邻的数组元素差4个字节,即0x7ffee4065820 与 0x7ffee4065824 差了一个4;其余的同理。

如图:

数组内存

可以看出C++中二维数组在地址空间上是连续的。

比如Java就是没有指针的,同时也不对程序员暴露其元素地址,寻址操作完全交给虚拟机,所以看不到每个元素的地址情况。

以Java一个例子为证

1
2
3
4
5
6
7
public static void test_arr() {
int[][] arr = {{1, 2, 3}, {3, 4, 5}, {6, 7, 8}, {9,9,9}};
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
}

输出地址为:

1
2
3
4
[I@7852e922
[I@4e25154f
[I@70dea4e
[I@5c647e05

这里数值也为16进制,但不是真正的地址,而是经过处理后的数值了。可以看出二维数组的每一行头结点的地址是没有规律的,即不连续。

所以Java的二维数组可能是如下了排列的方式:

算法通关数组3