数据结构数据结构

1. 数组:为什么很多编程语言中数组都是从0开始?

2020-07-11  本文已影响0人  一角钱技术

1. 数组:为什么很多编程语言中数组都是从0开始?

在大部分编程语言中,数组都是从0开始编号的,但你是否下意识想过,为什么数组要从0开始编号,而不是1开始呢? 从1开始不是更符合人类的思维习惯吗?下面以这个问题来学习数组。

数组的基本概念与特性

什么是数组?

什么是数组?估计你心中已经有了答案。不过,这里还是总结一下。数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据
这里定义里有几个关键词,理解了这几个关键词,就能彻底掌握数组的概念了。

线性表(Linear List)。顾名思义,线性表就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。除了数组,链表、队列、栈等也是线性表结构。

而与它相对立的概念是非线性表,比如二叉树、堆、图等。之所以叫非线性,是因为在非线性表中,数据之间并不是简单的前后关系。

总结下数组的特性

正是因为这两个限制,它才有一个堪称“杀手锏”的特性 “随机访问” 。但有利就有弊,这两个限制也让数组的很多操作变得非常低效,比如要想在数组中删除、插入一条数据,为来保证连续性,就需要左大量的数据搬移工作。

如何实现随机访问?

数组到底是如何实现根据下标随机访问数组元素的?
例如:长度为 10 的 int 类型的数组 int[] a = new int[10]

  1. 计算机给数组 a[10] ,分配了一块连续内存空间 1000 ~ 1039
  2. 内存块的首地址为 base_address = 1000
  3. 计算机会给每个内存单元分配一个地址,计算机通过地址来访问内存中的数据。

当计算机需要随机访问数组中的某个元素时,它会通过下面的寻址公式,计算出该元素存储的内存地址:
a[i]_address = base_address + i * data_type_size

arr[i] 首地址 = 数组内存块首地址 + 数据类型大小 * i,其中 i 为偏移量,其中 data_type_size 表示数组中每个元素的大小。

上面这个例子里面:
base_address :内存块的首地址。
data_type_size : 表示数组中每个元素的大小,比如目前数组中存储的是 int 类型数据,所以 data_type_size 就为 4 个字节。

数组时间复杂度

数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。
注意点:

  1. 数组是一种线性表;
  2. 连续的内存空间和相同类型的数据。
    由于第二个性质,数组支持 “随机访问”,根据下标随机访问时间复杂度为 O(1),但是在数组中删除、插入数据时需要做数据搬移工作。

低效的“插入”和“删除”操作

1. 插入操作

假如数组的长度为 n,我们需要将一个数据插入到数据的第 k 个位置,则需要将 [k , n] 位元素都顺序地往后挪动一位。

2. 删除操作

和插入操作一样,为了保证内存的连续性,删除操作也需要搬移数据。

更高级用法

在某些特殊场景下,在不追求数组中数组的连续时,我们将多次删除操作集中在一起执行,会提高删除的效率?
例如:假设有一个数组 a , 长度为 10,存储了 8 个元素,分别为 a,b,c,d,e,f,g,h 。现在我们依次删除 a,b,c 三个元素:

a = [a,b,c,d,e,f,g,h];

为了避免 d,e,f,g,h 这个几个数据会被搬移 3 次,我们先记录已经删除的数据(每次删除操作并不是真正的搬移数据,只是记录数据已经被删除)。当 a 数组没有空间存储数据时,这才触发依次真正的删除操作,这样就减少了删除操作导致的数据搬移。

上述这个操作其实就是 JVM标记清除垃圾回收算法 的核心思想。

3. 警惕数组访问越界

在 C 语言中,只要不是访问受限的内存,所有的内存空间都是可以自由访问的。如果疏忽会造成严重的后果。当然,Java语言会自动检测。

4. 总结
**
数组是最基础、最简单的数据结构。数组用一块连续的内存空间,来存储相同类型的一组数据,最大特点就是随机访问元素,并且时间复杂度为 O(1)。但是插入、删除操作也因此比较低效,时间复杂度为O(n)。

数组和链表的区别

最后总结一下:为什么大多数编程语言中,数组要从 0 开始编号,而不是从 1 开始呢?

a[k]_address = base_address + k * type_size
但是,如果数组从1 开始计数,那我们计算数组元素 a[k] 的内存地址就会变为:
a[k]_address = base_address + (k-1)* type_size

对比两个公式,不难发现,从 1 开始编号,每次随机访问数组元素都多来一次减法运算,对于 CPU 来说,就多来一次减法指令。

数组作为非常基础的数据结构,通过下标随机访问数组元素又是其非常基础的编程操作,效率的优化就要尽可能做到极致,所以为来减少一次减法操作,数组选择来从 0 开始编号,而不是 1 开始。

以上谢谢大家,求赞求赞求赞!

💗 大佬们随手关注下我的wx公众号【一角钱小助手】和 掘金专栏【一角钱】 更多题解干货等你来~~

上一篇下一篇

猜你喜欢

热点阅读