数组定义
数组是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。
线性表
线性表就是数据排成一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。数组、链表、队列、栈等也是线性表。而像树、堆、图就是非线形
连续内存空间和相同的数据类型
正是有了连续内存空间和相同的数据类型,才能“随机访问”。如下图每个元素的内存地址a[i]_address = base_address + i * data_type_size。

低效的删除和插入操作
也是因为连续内存空间的限制,数组的删除和插入效率相对比较低
1.删除
比如数组a[n]。要删除第i位的元素,就必须把i+1~n-1位的统一向前移动一位。最好情况i就是最后一位,不需要移动元素时间复杂度为O(1)。如果不幸i就是第0个元素,那么n-1个元素需要移动,时间复杂度为O(n)。平均时间复杂度为(0+1+2+...+n-1)/n = O(n)
2.插入
比如数组a[n]。要在第i位要插入元素,就必须把i~n-1位统一向后移动一位。最好的情况i就在数组末尾,不需要移动任何元素时间复杂度为O(1)。最坏的情况是i为0在数组第一位,需要移动n个元素时间复杂度为O(n)。平均时间复杂度(1+2+...+n)/n = O(n)
容器
数组因为提前分配内存的特点长度必须是固定的,对于业务开发人员来说很不灵活,因为很多情况下在定义变量并不能精确的知道数据量的多少。为了方便很多编程语言提供了容器。比如go中的切片。这样的容器虽然方便的业务开发,但是他的底层依然用的是数组,当切片的长度大于底层数组长度,就需要重新开辟一块更大的连续空间。先copy再重新赋值。这个过程内存的申请和销毁,也是需要一定的时间(虽然这个在业务开发层面几乎感觉不到)。所以对于可以确定长度的情况下,还是建议使用数组替代容器。效率可能会高。
为什么大多数编程语言数组从0开始编号
1.数组下标可以其实就是距离首地址的偏移量,其实a[0]就是数组的首地址。回到上边说的数组每个元素的内存访问地址a[i]_address = base_address + i * data_type_size。如果编号从1开始公式就变成了a[i]_address = base_address + (i-1) * data_type_size。多了一次计算
2.应该一开始c语言就是从0开始为了减少开发的学习成本,以后语言多采用从0开始。