list - 在 Racket 中,列表相对于向量的优势是什么?

标签 list data-structures scheme racket

到目前为止,在我使用 Racket 的经验中,我没有过多考虑向量,因为我发现它们的主要好处——对元素的恒定时间访问——在你使用大量元素之前并不重要。

然而,这似乎不太准确。即使元素数量很少,向量也具有性能优势。例如,分配一个列表比分配一个向量要慢:

#lang racket

(time (for ([i (in-range 1000000)]) (make-list 50 #t)))
(time (for ([i (in-range 1000000)]) (make-vector 50 #t)))

>cpu time: 1337 real time: 1346 gc time: 987
>cpu time: 123 real time: 124 gc time: 39

并且检索元素也更慢:
#lang racket

(define l (range 50))
(define v (make-vector 50 0))

(time (for ([i (in-range 1000000)]) (list-ref l 49)))
(time (for ([i (in-range 1000000)]) (vector-ref v 49)))

>cpu time: 77 real time: 76 gc time: 0
>cpu time: 15 real time: 15 gc time: 0

顺便说一句,如果我们增加到 1000 万,这个性能比仍然成立:
#lang racket

(define l (range 50))
(define v (make-vector 50 0))

(time (for ([i (in-range 10000000)]) (list-ref l 49)))
(time (for ([i (in-range 10000000)]) (vector-ref v 49)))

>cpu time: 710 real time: 709 gc time: 0
>cpu time: 116 real time: 116 gc time: 0

当然,这些是综合示例,大多数程序不分配结构或使用list-ref。一百万次循环。 (是的,我故意捕获第 50 个元素来说明性能差异。)

但它们也不是,因为在一个依赖列表的整个程序中,每次触摸这些列表时都会产生一些额外的开销,所有这些小效率低下都会导致整体运行时间变慢程序。

因此我的问题是:为什么不一直使用向量?在什么情况下,我们应该期望列表有更好的性能?

我最好的猜测是因为从 中取出元素的速度一样快。正面 列表,例如:
#lang racket

(define l (range 50))
(define v (make-vector 50 0))

(time (for ([i (in-range 1000000)]) (list-ref l 0)))
(time (for ([i (in-range 1000000)]) (vector-ref v 0)))

>cpu time: 15 real time: 16 gc time: 0
>cpu time: 12 real time: 11 gc time: 0

...列表在递归情况下是首选,因为您主要使用 conscarcdr ,并且它节省了处理列表的空间(向量不能在不复制整个向量的情况下被破坏并重新组合在一起,对吗?)

但是在您存储和检索数据元素的情况下,无论长度如何,向量似乎都有优势。

最佳答案

由于list-ref使用与索引线性的时间,除非用于短列表,否则很少可以使用。但是,如果访问模式是顺序的并且元素的数量可以变化,那么列表就可以了。看到一个对 50 个元素长的 fixnums 列表的元素求和的基准会很有趣。

但是,对数据结构的访问模式并不总是顺序的。

以下是我如何选择在 Racket 中使用的数据结构:

DATA STRUCTURE   ACCESS       NUMBER     INDICES
List:            sequential   Variable   not used
Struct:          random       Fixed      names
Vector:          random       Fixed      integer
Growable vector: random       Variable   integer
Hash:            random       Variable   hashable
Splay:           random       Variable   non-integer, total order

关于list - 在 Racket 中,列表相对于向量的优势是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27584416/

相关文章:

python - 斐波那契调用图中的值分区(调用图是二叉树)

java - 为什么 compareTo 在应该为 false 时返回 true?

lisp - 语法从 'The Little Schemer' 中的示例更改为真实的 Scheme

scheme - 为什么Scheme 有list 和quote?

lisp - 在 Casting SPELls 中推送项目位置

c++ - 在迭代 std::list 时删除

带有来自列表的输入的 Python 调用类

c++ - 给定中序和后序遍历,如何输出树的前序遍历?

python - 如何通过选择元素中字符的唯一组合来过滤列表(Python)?

Python - 如果元素尚未包含在列表中,如何追加到列表中?