【问题标题】:Concatenate lists in constant time in scala?在scala中以恒定时间连接列表?
【发布时间】:2011-06-12 01:31:45
【问题描述】:

在 Scala 中,是否有用于在恒定时间内连接两个列表(或数组、向量或列表缓冲区等)的内置函数或外部库?这样的操作可能会破坏/改变两个原始列表。据我所知,我看到的所有用于连接列表的函数都以线性时间运行。

非常感谢。

【问题讨论】:

  • 你怎么可能在恒定时间内复制 N 个(即可变数量)项目?
  • @delnan:他没有要求复制这些值。例如,您可以通过创建以两棵树作为子节点的新根来在恒定时间内连接两棵二叉树。 (在这种情况下,您必须看到“序列”的松散含义的“列表”。)
  • 看看是否可以使用 DList。见stackoverflow.com/questions/3352418/what-is-a-dlist。最终,您仍然需要一个线性运算来构建最终列表,但它可能是最接近现成可用的东西。

标签: list scala data-structures concatenation


【解决方案1】:

UnrolledBufferconcat 方法采用另一个 UnrolledBuffer 并在 O(1) 中返回它们的连接。它对参数缓冲区具有破坏性 - 在调用此方法后第二个缓冲区将是空的。

【讨论】:

  • 这正是我想要的。非常感谢。
【解决方案2】:

函数式语言中解决恒定时间追加的经典(至少可以追溯到Hughes '84)方法是通过"difference lists",其中追加到列表被编码为函数组合。

这是 Haskell 中的一个草图:

newtype DList a = DL { unDL :: [a] -> [a] }

所以 DList 是一个从列表到列表的函数。一些介绍形式:

-- The empty list is the identity function
empty       = DL id    

-- Singletons are the compositions of the cons function
singleton   = DL . (:)

-- Appending two lists is just composition
append xs ys = DL (unDL xs . unDL ys)

完整的实现是on Hackage,翻译成Scala应该很简单。

【讨论】:

【解决方案3】:

我在想DoubleLinkedList 可以提供恒定时间追加,因为您可以将一个列表的末尾连接到另一个列表的开头,而无需遍历其中一个。

但是,scala.collections.mutable.DoubleLinkedListjava.util.List 都不是这样工作的。

原因可能是这意味着a.append(b) 会同时修改ab,这是出乎意料的。

【讨论】:

    【解决方案4】:

    这是一个简单的不可变数据结构,支持恒定时间连接。它只是表明它是可能的,但并不打算用于实际用途。用于检索元素的 items 实现的运行时间非常糟糕,可以通过使用迭代器遍历树来轻松改进。

    我想知道是否有更好的数据结构?

    sealed abstract class Tree[+T] {
      def items: List[T]
      def append[U >: T](v: U): Tree[U] = this append Leave(v)
      def append[U >: T](other: Tree[U]) = Node(this, other)
    }
    
    case class Node[+T](val left: Tree[T], val right: Tree[T]) extends Tree[T] {
      def items = left.items ++ right.items
    }
    
    case class Leave[+T](val value: T) extends Tree[T] {
      def items = List(value)
    }
    
    case object EmptyTree extends Tree[Nothing] {
      def items = Nil
    }
    
    object ConstantTimeConcatenation {
      def main(args: Array[String]) {
        val first = EmptyTree append 1 append 2 append 3
        val second = EmptyTree append 4 append 5
        val both = first append second // runs in linear time
        println(both.items)
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-13
      • 1970-01-01
      • 2013-07-25
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多