我们在学习任何一种语言的时候,都会遇到数组这种数据类型,但是你是否下意识的想过为啥数组的下标是从0开始编号,而不是从1开始编号?
1.首先来对数组做一个定义:
数组(Array)是一种线性表数据结构,它用一组连续的内存空间,来存储一组具有相同类型的数据。
1)名词解释---线性表:线性表就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后俩个方向!
线性表与非线性表做对比:
2)名词解释--连续的内存空间和相同类型数据。
例如:
好处:数组可以随机访问,怎么随机访问呢?
公式:a[i]_address = base_address + i * data_type_size( data_type_size:数组中每个元素的大小,图中的例子大小为4,baseAddress=1000)
坏处:不适合插入和删除---》因为涉及到数据的迁移
面试中常见的问题:数组和链表的区别!
表述不准确的回答:链表适合插入和删除,时间复杂度为O(1),数组适合查找,时间复杂度也为O(1)
准确回答:数组是适合查找操作,根据下标进行随机访问的时间复杂度为O(1),(如果你使用二分查找,时间复杂度为O(logn))
2.低效的删除和插入
怎么去增加插入和删除的效率呢?
插入:(本来是cde要往后去迁移,现在直接放在最后一个位置 复杂度由原来的O(n)-->(1+2+.....+n)/n 变为O(1))
删除:(假设我们删除a,b,c三个元素,我们采取的做法不是删除一个a之后就立马把后面的往前移,而是把这个位置空着,只是记录数据已经被删除,等到数组的空间不够的时候再一次性的移位)
类比:JVM标记清楚垃圾回收算法的核心思想
3.容器能否替代数组?
1.就像java里面的arrayList其实是对数组的封装,可以实现数据的迁移以及扩容操作,所以我们在平时的业务中使用是可以的,很方便,损失一点点性能,但是如果是在做一些非常底层的开发,比如开发网路框架,性能的优化必须要做到极致,这个时候数组就优于容器。
4.解答开篇的问题
如果数组下标从0开始---》a[k]_address = base_address + k * data_type_size
如果数组下标从1开始---》a[k]_address = base_address + (k-1) * data_type_size--->(这里的k-1操作相当于计算机要执行一条指令,所以相对而言,效率较低)