《数据结构与算法之美》学习01

刚才听了几节极客时间的《数据结构与算法之美》,其中《05 | 数组:为什么很多编程语言中数组都从0开始编号?》一节讲了从0开始编号的原因,并且在课后留了两个问题,1.回顾下标记清除垃圾回收算法,2.二维数组的内存寻址公式是怎样的。看了评论区的内容,大开眼界,非常精彩,通俗易懂的把这两个问题说清楚了,之前看书的时候可能还一点疑惑,现在明白了,评论区真是高手如云。

从0开始编号的原因,主要是以下两个:

从 1 开始编号,每次随机访问数组元素都多了一次减法运算,对于 CPU 来说,就是多了一次减法指令。

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

说数组起始编号非 0 开始不可。所以我觉得最主要的原因可能是历史原因。

C 语言设计者用 0 开始计数数组下标,之后的 Java、JavaScript 等高级语言都效仿了 C 语言,或者说,为了在一定程度上减少 C 语言程序员学习 Java 的学习成本,因此继续沿用了从 0 开始计数的习惯。实际上,很多语言中数组也并不是从 0 开始计数的,比如 Matlab。甚至还有一些语言支持负数下标,比如 Python。

JVM标记清除算法:

大多数主流虚拟机采用可达性分析算法来判断对象是否存活,在标记阶段,会遍历所有 GC ROOTS,将所有 GC ROOTS 可达的对象标记为存活。只有当标记工作完成后,清理工作才会开始。

不足:1.效率问题。标记和清理效率都不高,但是当知道只有少量垃圾产生时会很高效。2.空间问题。会产生不连续的内存空间碎片。

二维数组内存寻址:

对于 m n 的数组,a [ i ][ j ] (i < m,j < n)的地址为:
address = base_address + ( i
n + j) * type_size