繁体   English   中英

Scala中模式匹配的时间复杂度是多少?

[英]What is the time complexity of Pattern matching in scala?

时间复杂度是否取决于要匹配的内容,还是将其编译成某种形式的可以进行O(1)查找的查找表?

某些Scala的 match 语句可以编译为与Java的 switch 语句相同的字节码。 有一个注释可以确保这一点。
但是,在大多数情况下,尤其是诸如解构之类的复杂情况,它将被编译为与一系列if / else 语句相同的字节码。

通常,我不希望它们是“恒定”操作,而是“线性”操作。 无论如何,由于输入的最大检查数不会改变,通常不会超过十个。 正式地说,它具有O(1)复杂度。
有关此问题的更详细说明,请参见yǝslA的回答。

如果您担心,可以先提出最常见的案例,然后再提出其他案例。 但是,我不太在意它的性能,您的应用程序不会真正注意到它。 我更喜欢代码的可读性和正确性。

大多数情况下,模式匹配将为O(1)因为您通常是针对少量或可能的情况进行匹配,并且每个匹配平均包括一些恒定时间操作。

由于模式匹配是通过在匹配的对象文档上调用unapply方法并可选地比较提取的值来实现的,因此时间复杂度将取决于 unapply方法的实现,并且可能具有任何复杂度。 对于一般情况,不可能进行编译器优化,因为某些模式匹配取决于传递给它们的数据。

比较这些方案:

List(1, 2, 3) match {
  case  _ :+ last => ... // O(n) with respect to list length
  case head :: tail => ... // O(1) w.r.t. list length
  case _ => ... // O(1) - default case, no operation needs to be done
}

在大多数情况下,我们会使用模式匹配列表(例如list)以使用:: - O(1)进行头部和尾部拆分,因为unapply只是在存在head情况下简单地返回head

我们通常不使用:+因为它不常见且昂贵(库代码):

/** An extractor used to init/last deconstruct sequences. */
object :+ {
  /** Splits a sequence into init :+ last.
   * @return Some((init, last)) if sequence is non-empty. None otherwise.
   */
  def unapply[T,Coll <: SeqLike[T, Coll]](
      t: Coll with SeqLike[T, Coll]): Option[(Coll, T)] =
    if(t.isEmpty) None
    else Some(t.init -> t.last)
}

为了获得序列的最后一个元素( t.last ),我们需要循环,即O(n)

因此,这实际上取决于模式匹配的方式,但是通常情况下,模式匹配案例类,元组,选项,集合以获取第一个元素而不是最后一个,等等。在绝大多数情况下,您将获得O(1)时间复杂度和大量的类型安全性。

另外:

在最坏的情况下,这里将有m的图案上平均每做c操作进行匹配(假定unapply有一定的时间,但也有例外)。 此外,将存在一个具有n属性的对象,我们需要将其与这些模式进行匹配,从而使我们总共进行了m * c * n操作。 但是,由于m很小(模式永远不会动态增长,通常由人类编写),因此我们可以安全地将其称为常数b给我们: T(n) = b * c * n 用big-O表示: T(n) = O(n) 因此,我们建立了O(n)理论界限,适用于需要检查对象的所有n属性的情况。 正如我在上面指出的那样,在大多数情况下,我们不需要检查所有属性/元素,例如当我们使用head :: tail ,其中n被常量替换为O(1) 只有当我们总是做诸如head :+ tail我们才会得到O(n) 对于您程序中的所有情况,我认为摊销成本仍为O(1)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM