Lisp gethash的复杂性

时间:2018-10-06 16:48:25

标签: algorithm lisp common-lisp hashtable

gethash函数的时间复杂度是多少? 例如,在c ++中,map的搜索量为O(log(n)),而unordered_map的搜索量为O(1)。这两件事都是用描述写的,但是我在Lisp中找不到gethash的任何此类引用。

实际上,这扩展到了所有标准库函数。我在哪里可以找到它们的复杂性?如果重要,请谈论sbcl。

3 个答案:

答案 0 :(得分:8)

ANSI CL 标准未指定算法复杂度的原因 库函数不是它的工作。该标准描述了行为,并将 performance 留给了特定于实现的文档。 假定所有实现都将提供最佳的理论性能(否则没人会使用它)。

要回答您的特定问题,在所有实现中,gethashO(1)

答案 1 :(得分:3)

通常的期望是GETHASH的Lisp实现在 O(1)中运行。

但是它可能具有令人惊讶的隐藏成本。 复制垃圾收集器(某些GC在其中)可能会在内存中复制哈希表。然后,这可能会触发表的重新哈希处理。

答案 2 :(得分:0)

该标准并未也不应告诉您gethash之类的功能的复杂性。试想一下,如果这样做的话:这将限制语言的实现,以使用与标准的复杂性一致的功能的实现。如果有人想出一个更好的哈希函数,那么实现将无法使用它。

好吧,您可能会说这很愚蠢:该标准只需要指定复杂性的上限。这将允许实现使用它喜欢的任何更好的功能,对吗?但这也不是答案:可能存在(并且在许多情况下)算法在最坏情况下的性能很差,但预期性能却好得多。我认为,要在标准中处理该问题要么是不可能的,要么将其完全覆盖在可接受的复杂程度以及何时以及何时不可接受的复杂描述中。

提供较高的复杂性界限也将排除那些想要在(例如)实现的复杂程度和性能之间进行权衡的实现:在某些情况下,应允许实现的哈希表位于内部,例如alists:对于少数几个按键,这些通常非常快,但是对于大量的按键,它们的性能却有所下降。应该允许这样的实现。


在某些情况下,事物的复杂性从标准中是显而易见的:显然,length的时间复杂度在列表的长度上是线性的(除了它可能不终止)如果列表是循环的)。但这是不正确的:没有什么可以阻止实现将某个长度值保持在某个位置,这在某些情况下会使length成为恒定时间。显然,这将是英雄主义(我认为在实现上难以置信)和无用的优化,但这并不是排除该标准的地方。

作为一种语言(不是CL的实现)执行类似操作的示例,请考虑对Racket的list?谓词的描述:

  

如果 v 是列表,则返回#t:空列表或第二个元素是列表的一对。由于内部缓存,此过程有效地花费了恒定的时间(因此,对的任何必要遍历在原则上都可以算作分配对的额外成本)。

我不完全理解这一点,但是我认为Racket必须在其cons对象中实现一个标志,该标志告诉您其cdr是一个正确的列表,然后依靠不变性来知道这是真的,它总是真正。如果CL具有这样的功能,那么使其很难在恒定时间内运行会很困难。