开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
数组可以说是一种最简单的数据结构,它在内存中是连续分布的。无论是创建静态数组还是动态数组,都需要我们指定该数组的大小,然后根据元素的大小分配内存。
数组的空间是连续的
无论是一维数组还是二维数组,空间上都是连续分布的,下面是一个小例子
一维数组
char arr[5];
printf("%p\n", &arr[0]);
printf("%p\n", &arr[1]);
printf("%p\n", &arr[2]);
printf("%p\n", &arr[3]);
printf("%p\n", &arr[4]);
二维数组
char arr[2][2];
printf("%p\n", &arr[0][0]);
printf("%p\n", &arr[0][1]);
printf("%p\n", &arr[1][0]);
printf("%p\n", &arr[1][1]);
可以看出是连续分布的
数组的空间效率并不是很好
当我们不知道数组要预先设置多少的时候,为了保证数组的大小够用,一般都比较大一点,假设为10,当我们只储存一个元素的时候,就会造成空间的浪费。
数组的时间效率好
数组是连续存储的并且可以用下标直接进行访问,所以它的读/写都是O(1),而查找的效率则是O(N)。
解决数组的空间效率问题,在C语言中,用relloc进行扩容。
在C++的STL中用vector,vector每次扩容时,新的容量都是原来的2倍。
虽然这样都能解决空间大小的问题,但是在扩容的时候需要把原来的数据重新拷贝到新的数组中,然后释放原来的空间。因为每一次扩容都有额外的操作,所以尽量减少扩容的次数。
数组和指针
数组名就是一个指针,它指向数组的第一个元素,只不过它是一个常量,不能被改变。 但是它不是一个普通的指针,它和指针还是有区别的。 下面用代码讲解一下他们的区别
int f(int arr[])
{
return sizeof(arr);
}
int main()
{
int a[] = { 1,2,3,4,5,6 };
int* p = a;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(p));
printf("%d\n", f(a));
return 0;
}
a是一个数组,数组里面有6个元素,每个元素的大小为4,所以
sizeof求的是数组的总大小。
sizeof(p)求的就是一个指针的大小,32位平台下大小为4,64位平台下大小位8。
对于f(a),虽然传的是数组,但是此数组非彼数组,它已经退化成普通的指针了;而且形参写的是数组的形式,本质还是指针。所以还是4.