数组理论基础
参考链接:代码随想录 https://www.programmercarl.com/数组理论基础.html#数组理论基础
要知道数组在内存中的存储方式,才能真正理解数组相关的面试题。
数组是存放在连续内存空间上的相同类型数据的集合。
数组可以方便地通过下标索引的方式获取下标下对应的数据。
举一个字符数组的例子,如下图所示:
需要注意的两点是:
1. 数组的下标都从0开始
2. 数组内存空间的地址是连续的
正因为数组在内存空间的地址是连续的,所以我们在删除或者添加元素的时候,难免要移动其他元素的地址。
例如删除下标为3的元素,需要对下标为3的元素后边的所有元素做移动操作,如下图所示:
而且如果使用C++的话,需要注意vector和array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。
数组的元素不能删,只能覆盖。
二维数组如下图所示:
那么二维数组在内存的空间地址是连续的吗?
不同编程语言的内存管理是不一样的,以C++为例,在C++中二维数组是连续分布的。
我们可以做一个实验,C++测试代码如下:
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(); }
测试地址为:
0x7ffee4065820 0x7ffee4065824 0x7ffee4065828 0x7ffee406582c 0x7ffee4065830 0x7ffee4065834
地址为16进制,可以看出二维数组地址是连续一条线。
0x7ffee4065820 与 0x7ffee4065824 差了一个4,也就是4个字节,因为这是一个int型数组,所以两个相邻数组元素的地址差4个字节。
0x7ffee4065828 与 0x7ffee406582c 也是差了4个字节,在16进制里8 + 4 = c,c就是12。
可以看出C++中二维数组在地址空间上是连续的。
Java没有指针,同时也不对程序员暴露元素的地址,寻址操作完全交给虚拟机。
所以看不到每个元素的地址情况,以Java为例,做一个实验:
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]); }
输出的地址为:
[I@7852e922 [I@4e25154f [I@70dea4e [I@5c647e05
这里的数值也是16进制,这不是真正的地址,而是经过处理后的数值,我们可以看出,二维数组的每一行头结点的地址是没有规则的,更谈不上连续。
所以Java的二维数组可能是如下排列的方式: