如何实现Scala不可变索引序列以及它们的操作的复杂性是什么?

时间:2014-04-13 08:28:06

标签: scala time-complexity scala-collections seq

我模糊地回忆起Scala的不可变索引序列操作是 O(log n),但是对数的基数足够大,所以出于所有实际目的,操作几乎就像< EM> O(1)。这是真的吗?

IndexedSeq如何实现此目标?

2 个答案:

答案 0 :(得分:4)

immutable.IndexedSeq的默认实施是Vector。以下是relevant documentation关于其实施的摘录:

  

向量表示为具有高分支因子的树(树的分支因子或图形是每个节点处的子节点数)。每个树节点最多包含32个向量元素或最多包含32个其他树节点。具有多达32个元素的向量可以在单个节点中表示。具有多达32 * 32 = 1024个元素的向量可以用单个间接表示。从树根到最终元素节点的两跳足以用于具有最多2 ^ 15个元素的向量,用于具有2 ^ 20的向量的三个跃点,用于具有2 ^ 25个元素的向量的四个跃点以及用于具有向上的向量的五个跃点到2 ^ 30个元素。因此,对于所有合理大小的向量,元素选择涉及最多5个基本数组选择。当我们写下元素访问是“有效的恒定时间”时,这就是我们的意思。

immutable.HashSetimmutable.HashMap是使用类似技术实现的。

答案 1 :(得分:2)

IndexedSeq是一个Vector,它是一个树(实际上是trie)结构,扇出为32.因此,不计算内存位置,你永远不会超过O(log n)因子大约6 - 与二叉树比较,范围从1到30。

也就是说,如果你计算内存局部性,你会发现索引到1G元素Vector和10元素Vector之间存在巨大差异。 (你会注意到Array也有很大差异。)