假设我们需要一个数字列表,有两个定义:
(def vector1 [1 2 3])
(def list2 '(1 2 3))
那么主要的区别是什么?
答案 0 :(得分:31)
[1 2 3]
是vector,而'(1 2 3)
是list。这两种数据结构有不同的性能特征。
向量提供对其元素的快速索引随机访问(v 34)
在v
时间内在索引34
返回向量O(1)
的元素。另一方面,修改向量通常更昂贵。
列表很容易在头部和/或尾部修改(取决于实现),但提供对元素的线性访问:(nth (list 1 2 3 4 5) 3)
需要顺序扫描列表。
有关性能权衡的更多信息,您可以谷歌“向量与列表性能”或类似的东西。
[跟踪处理]
好的,让我们进一步了解一些细节。首先,向量和列表是不是特定于Clojure的概念。与 maps ,队列等一起,它们是数据集合的抽象类型。对数据进行操作的算法是根据这些抽象来定义的。 向量和列表是定义的由我上面简要描述的行为(即是向量如果它有大小,你可以通过它来访问它的元素并在恒定时间内索引等。)。
与其他任何语言一样,Clojure在提供以这种方式调用的数据结构时希望满足这些期望。如果您查看basic implementation of nth
in vector
,您会看到arrayFor
方法的调用,其复杂性为 O(log 32 N)以及在Java数组中查找 O(1)。
为什么我们可以说(v 34)
实际上是 O(1)?因为Java int
的 log 32 的最大值大约为 7 。这意味着对矢量的随机访问事实上常量时间。
总之,vectors
和lists
之间的主要区别是的性能特征。此外,正如Jeremy Heiler指出的那样,在Clojure中,行为存在逻辑上的差异,即使用conj
增加集合。
答案 1 :(得分:8)
列表和向量之间存在两个主要区别。
列表在逻辑上生长在头部,而矢量逻辑上在尾部生长。使用conj
函数时,您可以看到这一点。它将根据给定的集合类型增加集合。虽然您可以在任何一方增加集合,但以这种方式执行此操作是有效的。
为了检索列表中的第n个项目,需要从头部遍历列表。另一方面,向量不会遍历并返回O(1)中的第n个项目。 (它确实是O(log32n),但这是由于集合如何实现为持久集合。)
答案 2 :(得分:4)
向量评估时间不是O(1)它是log32N
向量(IPersistentVector) Vector是由连续整数索引的值的集合。向量支持通过log32N跃点中的索引访问项目。 count是O(1)。 conj将项目放在向量的末尾。向量还支持rseq,它以相反的顺序返回项目。向量实现IFn,用于一个参数的invoke(),它们假定它是一个索引并且自己查找就好像是nth,即向量是它们索引的函数。
答案 3 :(得分:3)
向量保存相邻存储区域中的所有数据项 整个矢量的传输容易和插入或删除项目 与名单相比,价格昂贵。
列表保持项目是不相交的记忆区域,使得转移 整个列表昂贵但插入和删除单个项目 相对便宜。
经典矢量的大小也是固定的,并且限制为N个项目 列表可以动态增长和缩小。