作为数据容器,vector和list之间的主要区别是什么

时间:2012-07-16 12:22:35

标签: clojure

假设我们需要一个数字列表,有两个定义:

(def vector1 [1 2 3])
(def list2 '(1 2 3))

那么主要的区别是什么?

4 个答案:

答案 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 。这意味着对矢量的随机访问事实上常量时间。

总之,vectorslists之间的主要区别的性能特征。此外,正如Jeremy Heiler指出的那样,在Clojure中,行为存在逻辑上的差异,即使用conj增加集合。

答案 1 :(得分:8)

列表和向量之间存在两个主要区别。

  1. 列表在逻辑上生长在头部,而矢量逻辑上在尾部生长。使用conj函数时,您可以看到这一点。它将根据给定的集合类型增加集合。虽然您可以在任何一方增加集合,但以这种方式执行此操作是有效的。

  2. 为了检索列表中的第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个项目 列表可以动态增长和缩小。

  • Vectors还提供对元素项的索引访问。列表没有。 经典载体的前身是一个数组。
  • 矢量的现代实现通常旨在提供类似的 特征,但基础数据结构实际上可能是一个 列表或散列,这些向量通常支持动态 重新调整大小。