数据结构精讲:从原理到实战--学习笔记01

数据结构精讲:从原理到实战–学习笔记01

本笔记是记录学习 《数据结构精讲:从原理到实战》,作者是:蔡元楠,Google Brain资深工程师。

如有侵权,联系删除!

数组内存模型

一维数组

当定义一个数组后

int[] data = new int[5];

内存模型如图所示
Alt
这种连续空间的内存模型揭示了一个重要特性:随机访问(random access)
random access:可以用同等的时间访问到一组数据中的任意一个元素。

我们可以用如下代码获取数组中的值:

data[0]

这种从 0 开始进行索引的编码方式被称为是“Zero-based Indexing
我们可以通过以下公式获取数组特定元素:

base_address + index * date_size = target_address

此公式保证了,不同的数组元素达到的时间是相同的。

二维数组

一般称为一维数组为 向量(Vector)表(Table),数学上称二维数组为 矩阵(Matrix)

按照以下代码声明一个矩阵:

int[][] data = new int[2][3]

基于这个二维数组,我们是无法确定 data[0][1]的内存地址,因为这个问题涉及到二维数组在内存中的寻址方式。其本质是 行优先(Row-Major Order) 还是 列优先(Column-Major Order)

Alt
在行优先内存模型中,每一行的相邻元素保存在相邻的连续内存空间中,这个二维数组内存模型如下所示:
Alt
我们可以按照以下公式获取data[i][j]里的元素:

base_address + data_size * (i * number_of_column + j)

在列优先内存模型中,每一列的相邻元素保存在相邻的连续内存空间中,这个二维数组内存模型如下所示:
Alt
我们可以按照以下公式获取data[i][j]里的元素:

base_address + data_size * (i * number_of_row + j)

CPU 在读取内存数据的时候,通常会有一个 CPU 缓存策略。也就是说,在 CPU 读取程序指定地址的数值时,CPU 会把和它地址相邻的一些数据也一并读取并放到更高一级的缓存中,比如 L1 或者 L2 缓存。当数据存放在这种缓存上的时候,读取的速度有可能会比直接从内存上读取的速度快 10 倍以上。

数组特点

高效的访问和低效的插入删除

数组的访问时间复杂度是 O(1)

对于保存基本类型Primitive Type)的数组来说,它们的内存大小在一开始就已经确定好了,我们称它为静态数组(Static Array)。静态数组的大小是无法改变的,所以我们无法对这种数组进行插入或者删除操作。但是在使用高级语言的时候,比如 Java,我们知道 Java 中的 ArrayList 这种 Collection 是提供了像 add 和 remove 这样的 API 来进行插入和删除操作,这样的数组可以称之为动态数组(Dynamic Array)

为了维持数组内存中的连续性,当插入一个数据时,需要把待插入节点及之后所有的数据都拷贝,然后给数组扩容,把拷贝的数据放入待插入节点之后,最后再在待插入节点插入目标值。
删除元素同理,所以插入删除时间复杂度是 O(n)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章