在我的算法中替换命令式 PriorityQueue

Posted

技术标签:

【中文标题】在我的算法中替换命令式 PriorityQueue【英文标题】:Replacing imperative PriorityQueue in my algorithm 【发布时间】:2011-07-18 19:23:52 【问题描述】:

我目前有一个使用 scala.collection.mutable.PriorityQueue 以特定顺序组合元素的方法。例如代码看起来有点像这样:

 def process[A : Ordering](as: Set[A], f: (A, A) => A): A = 
   val queue = new scala.collection.mutable.PriorityQueue[A]() ++ as
   while (queue.size > 1) 
     val a1 = queue.dequeue
     val a2 = queue.dequeue
     queue.enqueue(f(a1, a2))
   
   queue.dequeue
 

代码按照编写的方式工作,但必须非常必要。我曾想过使用 SortedSet 而不是 PriorityQueue,但我的尝试使这个过程看起来更加混乱。什么是做我想做的事情的更明确、更简洁的方式?

【问题讨论】:

【参考方案1】:

如果 f 不产生已经在 Set 中的元素,你确实可以使用 SortedSet。 (如果是这样,您需要一个不可变的优先级队列。)执行此操作的声明式方法是:

def process[A:Ordering](s:SortedSet[A], f:(A,A)=>A):A = 
  if (s.size == 1) s.head else 
    val fst::snd::Nil = s.take(2).toList
    val newSet = s - fst - snd + f(fst, snd)
    process(newSet, f)
  

【讨论】:

我不得不说 OP 的命令式版本更清晰。如果有一个多项目的出队功能会很有用...... 我把它清理了一下,现在看不到关于 OP 版本的更清楚的地方。这只是你习惯的问题。 我不认为这只是你使用它的原因。它是 s - fst - snd +... 等等。不使用 dequeue 意味着你要做两次事情 - 一次访问两个顶部元素以将它们传递给 f。一次构建没有它们的队列的其余部分。 Dequeue 巧妙地捕获了这两者。返回前两个和队列其余部分的提取器可能会有所帮助?【参考方案2】:

试图改进@Kim Stebel 的答案,但我认为命令式变体仍然更清晰。

def process[A:Ordering](s: Set[A], f: (A, A) => A): A = 
  val ord = implicitly[Ordering[A]]
  @tailrec
  def loop(lst: List[A]): A = lst match 
    case result :: Nil => result
    case fst :: snd :: rest =>
      val insert = f(fst, snd)
      val (more, less) = rest.span(ord.gt(_, insert))
      loop(more ::: insert :: less)    
  
  loop(s.toList.sorted(ord.reverse))

【讨论】:

【参考方案3】:

这是SortedSetStream 的解决方案:

def process[A : Ordering](as: Set[A], f: (A, A) => A): A = 
    Stream.iterate(SortedSet.empty ++ as)(  ss => 
        ss.drop(2) + f(ss.head, ss.tail.head))
    .takeWhile(_.size > 1).last.head

【讨论】:

这可能是一个不同的问题,但在这种情况下是否有理由更喜欢 Stream.iterate 而不是 Iterator.iterate? @Garrett 根本没有——事实上恰恰相反。但是Iterator 不起作用,如果用功能替换“命令式”代码......

以上是关于在我的算法中替换命令式 PriorityQueue的主要内容,如果未能解决你的问题,请参考以下文章

用 Priorityqueue 替换 LinkedList。显示的错误是 java.lang.ClassCastException

java priorityQueue更新问题

在C中制作一个计算PriorityQueue中元素数量的函数

挑战程序设计竞赛(算法和数据结构)——10.5 Java 中对应C++ STL中的PriorityQueue类的使用

Java数据结构及算法实战系列011:数组实现的优先级队列PriorityQueue

Java数据结构及算法实战系列011:数组实现的优先级队列PriorityQueue