Scala方法的渐近行为

时间:2011-10-19 10:45:00

标签: scala time-complexity

我是否可以找到HashSet,TreeSet,List等集合上的预期时间空间复杂性?

是否只是希望从抽象数据类型本身的属性中知道这些?

我知道Performance characteristics for Scala collections,但这只提到了一些非常基本的操作。也许这些集合的其余操作纯粹是从一个小的基础集构建的,但是,似乎我只是希望知道他们已经以这种方式实现了它们?

2 个答案:

答案 0 :(得分:8)

其他方法的指南应该是 - 只考虑一个有效的实现应该是什么样的。

集合上的大多数其他批量操作(处理集合中每个元素的操作)都是O(n),所以在那里没有提到它们。示例包括filtermapforeachindexOfreversefind ......

返回像combinationspermutations这样的迭代器或流的方法通常是O(1)

涉及2个集合的方法通常为O(max(n, m))O(min(n, m))。这些是zipzipAllsameElementscorresponds,...

方法uniondiffintersectO(n + m)

排序变体自然是O(nlogn)。当前实施中groupByO(nlogn)indexOfSlice使用KMP算法且为O(m + n),其中mn是字符串的长度。

+::+patch等方法通常也是O(n),除非您正在处理对其进行操作的不可变集合的特定情况。问题更有效 - 例如,在功能List上添加元素或在Vector附加元素。

方法toX通常为O(n),因为它们必须迭代所有元素并创建新集合。一个例外是toStream懒惰地构建集合 - 所以它是O(1)。此外,只要X是集合toX的类型,只需返回this,即O(1)

迭代器实现应该有O(1)(摊销)nexthasNext操作。迭代器创建应该是最坏情况O(logn),但在大多数情况下是O(1)

答案 1 :(得分:4)

其他方法的性能特征确实难以断言。请考虑以下事项:

  • 这些方法都是基于foreachiterator实现的,并且通常在层次结构中处于非常高的水平。例如,Vector的{​​{1}}已在map上实施。 为了增加对伤害的侮辱,使用哪种方法实现取决于类继承的线性化。这也适用于任何称为帮助程序的方法。之前发生过这种变化导致无法预料的性能问题。 由于collection.TraversableLikeforeach都是iterator,因此任何改进的效果都取决于其他方法的专业化,例如O(n)size
  • 对于他们中的许多人来说,进一步依赖于提供的构建器的性能特征,这取决于调用站点而不是定义站点。

因此,结果是定义方法的位置 - 并且已记录 - 没有足够的信息来说明其性能特征,并且可能不仅取决于继承集合如何实现其他方法,而且甚至可以通过调用站点传递的从CanBuildFrom获取的对象Builder的性能特征。

充其量,任何此类文档都将根据其他方法进行描述。这并不意味着它不值得,但它并不容易实现 - 开源项目的艰巨任务取决于志愿者,他们通常按照自己喜欢的方式工作,而不是需要。