一,数组的定义
数组是一种线性表数据结构,它用一组连续的内存空间,来存储一组具有相同类型的数据。对关键概念的解释如下:
1,线性表
线性表就是数据排成像一条线一样的机构,每个线性表上的数据最多只有前和后两个方向。除数组,链表,队列,栈等都是线性表。
与其对应的是非线性表,比如二叉树,堆,图等,之所以叫非线性,是因为在非线性表中,数据之间并不是简单的前后关系。
2,连续的内存空间和相同类型的数据
这两个限制条件,才有了堪称“杀手锏”的特性:“随机访问”。同时也让数组的操作很低效。例如数组中的删除和插入一个数组,为了保持连续性,需要做大量的数据搬移工作。
二,数组如何访问元素
计算机会给每个内存单元分配一个地址,计算机通过地址来访问内存中的数据。当计算机需要随机访问数组中的某个元素时,它会首先通过下面的寻 址公式,计算出该元素存储的内存地址:
a[i]_address = base_address + i * data_type_size
其中data_type_size表示数组中每个元素的大小。
说明一下,链表与数值比较的区别:链表插入,删除时间复杂度是,也就是说链表的有点在于数据的插入和删除。数值的下标查找时间复杂度是,其他查找算法,例如二分查找法,即使是连续的数组,其时间复杂度是。所以正确的说不能简单的说数组的查找复杂度是。在数组某一位置插入和删除的效率低的原因是需要大规模的数据搬移。但在某种特定场景下,例如无序的数组中第k个位置插入新数据,原数据放到末尾,这样时间复杂就是。在快排中会用到。
三,数组的优势
在需要定义多维数组或者数据大小事先已知,并且对数据的操作非常简单时可以使用数组。
四,数组下标为何是从0开始
从数组存储的内存模型上来看,“下标”最确切的定义应该是“偏移(offset)”。前面也讲到,如果用a来表示数组的首地址,a[0]就是偏移为0的位置,也就是首地 址,a[k]就表示偏移k个type_size的位置,所以计算a[k]的内存地址只需要用这个公式: a[k]_address = base_address + k * type_size ;但是,如果数组从1开始计数,那我们计算数组元素a[k]的内存地址就会变为: a[k]_address = base_address + (k-1)*type_size; 对比两个公式,我们不难发现,从1开始编号,每次随机访问数组元素都多了一次减法运算,对于CPU来说,就是多了一次减法指令。
学习于极客时间 王争老师