faster/traditional 在 Scheme 中使用 append vs cons 和 reverse 吗?
Is it faster/traditional to use append vs cons and reverse in Scheme?
在 Scheme 中递归构建列表时,我看到了两种散布在 Internet 上的示例。每次迭代都会在新值后附加 append
。另一个是在每次迭代前添加一个新值 cons
然后在列表完成后 reverse
被调用一次。
我的直觉是后者更快,但如果 Scheme 解释器缓存了列表指针的结尾或正在做一些其他优化,那么前者将同样快速且可读性更强。如果解释器在做这个优化,是否保证在所有解释器中都可用?
始终首选使用 cons
。使用 append
是非常低效的,因为它总是遍历列表到末尾只是为了在那里添加一个新元素,而 cons
在开头添加元素。没有指向列表末尾的指针,因此根本没有执行您建议的优化。
当逐个元素构建大型列表时,这很重要,因为 cons
是一个 O(1)
操作,而 append
是 O(n)
添加的每个新元素,都会降低到 O(n^2)
复杂性! (一个很好的类比,参见:Schlemiel the Painter's algorithm)。最后,简单地在开头添加元素并在必要时在末尾添加 reverse
列表要便宜得多,从而实现 O(n)
复杂性。
在 Scheme 中递归构建列表时,我看到了两种散布在 Internet 上的示例。每次迭代都会在新值后附加 append
。另一个是在每次迭代前添加一个新值 cons
然后在列表完成后 reverse
被调用一次。
我的直觉是后者更快,但如果 Scheme 解释器缓存了列表指针的结尾或正在做一些其他优化,那么前者将同样快速且可读性更强。如果解释器在做这个优化,是否保证在所有解释器中都可用?
始终首选使用 cons
。使用 append
是非常低效的,因为它总是遍历列表到末尾只是为了在那里添加一个新元素,而 cons
在开头添加元素。没有指向列表末尾的指针,因此根本没有执行您建议的优化。
当逐个元素构建大型列表时,这很重要,因为 cons
是一个 O(1)
操作,而 append
是 O(n)
添加的每个新元素,都会降低到 O(n^2)
复杂性! (一个很好的类比,参见:Schlemiel the Painter's algorithm)。最后,简单地在开头添加元素并在必要时在末尾添加 reverse
列表要便宜得多,从而实现 O(n)
复杂性。