使用PriorityQueue的Scala问题非默认排序Stack [A]

时间:2010-11-29 04:12:57

标签: scala priority-queue

我正在尝试使用Scala编写一个耐心排序的简单实现 我已经正确设法创造了最初的桩;但是,我使用优先级队列来简化输出列表的生成让我很头疼。

看来我的订单执行错误或被忽略:

def PileOrdering = new Ordering[Stack[A]] {
    def compare(a : Stack[A], b : Stack[A]) = a.head.compare(b.head)
}

// Use a priority queue, ordering on stack heads (smallest stack elems)
val pq = new PriorityQueue[Stack[A]]()(PileOrdering)

// piles is a List[Stack[A]]
pq ++= piles

// Extract an ordered list of elements
val returnVal = (0 until count) map (_ => {
    val smallestList = pq.dequeue
    val smallestVal = smallestList.pop

    if (smallestList.length > 0){
        pq.enqueue(smallestList)
    }

    smallestVal
})

PriorityQueue似乎按(我想象默认的堆栈顺序)堆栈大小排序,而不是我的订购。

有什么事情突然显然是错误的吗? 任何帮助都会受到很大的欢迎 谢谢,

编辑:我在原始问题中没有说清楚:我正在使用Scala 2.8.1。
Edit2:我期望returnVal包含从最小到最大的元素排序,通过从所有堆栈的头部获取最小元素。丹尼尔指出,我的订购将从最大到最小的顺序排列我的堆栈(堆栈本身已经正确排序,最小元素在顶部),这似乎是问题。

2 个答案:

答案 0 :(得分:1)

根据排序,您是否对优先级队列中的第一个元素是最大值的元素感到困惑?代码似乎期望第一个元素是具有最小值的元素。

答案 1 :(得分:0)

稍微难以回答正在发生的事情,因为您没有将整个程序包含在输入和输出中。我的猜测是,这是由于2.8.1中PriorityQueue的旧实现。以下程序使用自定义排序,并使用堆栈列表填充优先级队列:

import collection._                                                                                                 
import collection.mutable.PriorityQueue                                                                             
import collection.mutable.Stack                                                                                     



class Test[A](piles: Traversable[Stack[A]])(implicit ord: Ordering[A]) {                                            

  def PileOrdering = new Ordering[Stack[A]] {                                                                       
    def compare(a : Stack[A], b : Stack[A]) = ord.compare(a.head, b.head)                                           
  }                                                                                                                 

  // Use a priority queue, ordering on stack heads (smallest stack elems)                                           
  val pq = new PriorityQueue[Stack[A]]()(PileOrdering)                                                              

  // piles is a List[Stack[A]]                                                                                      
  pq ++= piles                                                                                                      

}                                                                                                                   

object Main {                                                                                                       
  def main(args: Array[String]) {                                                                                   
    val t = new Test(Seq(Stack(1, 2, 3), Stack(15, 8), Stack(3, 4, 9, 0, -1), Stack(45, 1, 2, 3, 4)))               
    while (t.pq.nonEmpty) {                                                                                         
      println(t.pq.dequeue)                                                                                         
    }                                                                                                               
  }                                                                                                                 
}  

程序输出:

Stack(45, 1, 2, 3, 4)                                                                                               
Stack(15, 8)                                                                                                        
Stack(3, 4, 9, 0, -1)                                                                                               
Stack(1, 2, 3)

使用Scala主干,看起来是正确的。我应该指出PriorityQueue经历了一些更改,由于二进制兼容性原因,这些更改未包含在2.8.1中,但将在2.9中提供:

  • 它曾经是一个序列,它不再是一个序列 - applyupdate无法有意义地实现
  • 调用toString或迭代元素不会产生堆顺序 - 获取它的唯一方法是使用dequeue