漫谈数据结构——数组

188 阅读3分钟

这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战

前言

数组是我们在刚学习变成语言的时候都有学到,也有知道怎么使用?大家对于数组的初印象肯定是支持随机访问,以随机访问的方式指定索引获取数据的方式,我们先来介绍一下数据的概念:

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

其中线性表的概念指的是,数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。其实除了数组,链表、队列、栈等也是线性表结构。

其次数组是操作系统分配一组连续内存并且有相同类型数据的数据结构。这个特点,我们在平时的数据定义语句中就可以发现,如下使用Java定义一个数组:

// 定义了一个长度为3,并且存放的类型为int的数组
int[] numbers = new int[3];

// 定义了一个长度为2,并且存放的类型为long的数组
long[] longArr = new long[2];

结合上面的定义以及以上的两条定义数组的代码中,我们可以清晰的感受到定义的体现,那么接下来我们来讨论两个问题,一:数组为什么支持随机访问?二,二维数组如何支持随机访问。

数组为什么支持随机访问?

首先对于我们编写的程序而言,操作系统给我们提供了一个内存的高级抽象:我们只要把内存看作是一个巨大的字节数组即可,当今都是流行64位的机器,那么这个字节数组的大小是2^64 - 1比特,而内存的最小单位不是一个一个位去操作的,大多数的机器是以8位作为内存的最小寻址单位。

所以当我们的程序代码int[] numbers = new int[3]执行以后,操作系统会将一整块连续内存分配给数组变量numbers,假设首地址为0x00001000,那么接下来的两块则为0x0000100040x000010008,为什么是这样的地址呢,因为int类型占据4字节,一字节为8位,首字节地址为0x00001000,接下来的3字节也是存放第一个int变量的。所以第二个int的首字节地址肯定是第一个int的首字节地址加上类型大小,以此类推,那么我们就可以得到一个公式:

address = first_address + k * type_size

根据这个公式,我们就可以定位到数据任意一个变量的地址了。这也就是数组支持随机访问的原因。

二维数组如何支持随机访问

我们刚才讨论的就是基于一维数组,在Java中,我们还可以定义二维数组如下:

// 以下代码我们定义了一个3 ✖️ 3的二维数组。
int[][] nums = new int[3][3];

那么二维数组的公式是什么样呢?首先,我们可以把二维数组,先看做一个一维数组,我们就会得到上述的公式,那么我们的看做一维数组里面的第一个元素其实是一个数组,而不是一个int变量,所以要加上一个内部数组的偏置值,所以我们就会得到以下的公式:

int[][] nums = new int[m][n];
address = first_address + k * type_size + k * n * type_size

总结

今天我们讨论了数组的概念,以及简单分析了数据随机访问的特性。