数组

0x00 数组

数组时一种线性表结构,用一组连续的内存空间,来存储一组具有相同类型的数据

1、线性表

顾名思义就是数据排列成一条线一样的结构,每个数据最多只有前和后两个方向,线性表的结构是逻辑结构,在实际物理存储中分为顺序表和链表

a、顺序表,例如数组,在内存中为连续空间

b、链表,在内存中不一定连续,用指针连接,也构成线性结构

线性表还有队列、栈等,用顺序表和链表都可以实现

与之对应的就是非线形表,比如二叉树、堆、图等,数据之间不是简单的前后关系

2、连续的内存空间和相同类型的数据

正是因为这个限制,才使数组能够支持随机访问,当然也是因为维护这个特性,导致数组的插入和删除需要做大量的数据搬迁工作

随机访问指根据数组下标访问数组能达到O(1),不是指查找

就算是顺序数组,查找时间复杂度最快也是O(lgn),因为是连续的地址,所以根据数组头地址加上索引,可以立刻得到索引处数据的地址

3、插入和删除

为了位数连续的内存空间,插入和删除都需要做大量数据搬迁工作

最好的情况,插入或删除最后一个元素,不用搬迁数组,复杂度O(1)

最坏的情况,插入或删除第一个元素,后面所有的元素都需要前移或后移一位,复杂度O(n)

平均复杂度O(n)

4、容器和数组

针对数组类型,很多语言提出了容器类,例如java中的ArrayList

容器最大的好处是封装了很多数组处理的细节,支持动态扩容,动态扩容过程中会有很多数据搬迁工作,所以在使用容器时,如果能确定大小,最好提前指定

数组相对容器来说也有一些优势:

  • 容器只支持对象,数组支持基本类型,例如int、double类型,自动的装箱拆箱有一定的性能损耗
  • 如果数据大小事先已知,并且对数据的操作非常简单,用不到ArrayList的大部分方法,也可以直接使用数组

总的来说,如果不是非常底层的开发,对性能要求特别高,容器更方便使用

5、为什么很多编程语言中数组都是从0开始

如果a[0]表示首地址,a[k]表示k位地址

0开始
a[k]_address = base_address + k * type_size
1开始
a[k]_address = base_address + (k-1)*type_size

对比可以看出,从1开始多了一次减法操作,数组时非常基础的数据结构,为了效率优化做到极致,所以大部分变成语言的数组下标都是从0开始

你可能感兴趣的:(数组)