Scala优先级队列不维护排序

时间:2016-10-27 15:43:21

标签: scala data-structures queue priority-queue

我希望这是基于价格的顺序......

final case class Case(price: Int) {}

但它实际上是一个非常大的案例类,我从中删除了字段。我想这样排序......

val queue = PriorityQueue.empty[Case](Ordering.by((_: Case).price).reverse)

^按降价排序。

现在我希望排序保持......

queue.enqueue(Case(price = 2))
println(queue.toString)

queue.enqueue(Case(price = 3))
println(queue.toString)

queue.enqueue(Case(price = 4))
println(queue.toString)

queue.enqueue(Case(price = 1))
println(queue.toString)

queue.enqueue(Case(price = 0))
println(queue.toString)

但我的输出并没有排在第四和第五行...

PriorityQueue(Case(2))
PriorityQueue(Case(2), Case(3))
PriorityQueue(Case(2), Case(3), Case(4))
PriorityQueue(Case(1), Case(2), Case(4), Case(3))
PriorityQueue(Case(0), Case(1), Case(4), Case(3), Case(2))

此外,foreach方法不是按顺序迭代......

queue.foreach{ q =>
  print(q + ", ")
}

...打印

Case(0), Case(1), Case(4), Case(3), Case(2), 

如何让我的队列按降价排序?

3 个答案:

答案 0 :(得分:5)

根据Scala Documentation,打印队列不会显示优先级:

  

只有dequeue和dequeueAll方法才会返回方法   优先顺序(从堆中删除元素)。标准   收集方法包括drop,iterator和toString将删除   或者以最方便的顺序遍历堆。

     

因此,打印PriorityQueue不会显示优先顺序   虽然会打印出最高优先级的元素   第一。要按顺序打印元素,必须复制元素   PriorityQueue(例如,使用clone),然后将它们出列

因此,如果您想按顺序查看元素,则需要这样的内容:

scala> val queue = PriorityQueue.empty[Case](Ordering.by((_: Case).price).reverse)
queue: scala.collection.mutable.PriorityQueue[Case] = PriorityQueue()

scala> queue += Case(2) += Case(3) += Case(4) += Case(1) += Case(0)
res1: queue.type = PriorityQueue(Case(0), Case(1), Case(4), Case(3), Case(2))

scala> while (queue.size > 0) println(queue.dequeue)
Case(0)
Case(1)
Case(2)
Case(3)
Case(4)

或者您可以使用dequeueAll获取有序集合:

scala> val queue = PriorityQueue.empty[Case](Ordering.by((_: Case).price).reverse)
queue: scala.collection.mutable.PriorityQueue[Case] = PriorityQueue()

scala> queue += Case(2) += Case(3) += Case(4) += Case(1) += Case(0)
res2: queue.type = PriorityQueue(Case(0), Case(1), Case(4), Case(3), Case(2))

scala> val ordered = queue.dequeueAll                                                                      
ordered: scala.collection.immutable.IndexedSeq[Case] = Vector(Case(0), Case(1), Case(2), Case(3), Case(4)) 

scala> ordered.foreach(println)                                                                            
Case(0)                                                                                                    
Case(1)                                                                                                    
Case(2)                                                                                                    
Case(3)                                                                                                    
Case(4)                     

基于讨论 here,没有办法按顺序检索元素而不会通过出列来破坏队列。这似乎是底层数据结构(二进制堆)的实现所固有的。

答案 1 :(得分:1)

打印优先级队列可能不会返回订单中的元素。

但保证的是head始终返回最低(根据您的排序)元素,并按dequeue指定的顺序重复Ordering个出列元素。

当我这样做时:

queue.dequeue()
queue.dequeue()
queue.dequeue()
queue.dequeue()
queue.dequeue()

我明白了:

res10: Case = Case(0)
res11: Case = Case(1)
res12: Case = Case(2)
res13: Case = Case(3)
res14: Case = Case(4)

答案 2 :(得分:0)

是的,当优先级队列元素相等时,scala默认实现不是就地出队。您可以使用就地出队作为打击:

class PriorityQueueTest{
 implicit val ord: Ordering[(Any,Int)] = Ordering.by(_._2)

 var queue = mutable.PriorityQueue[(Any,Int)]()

 def inplaceDeque(number:Int): Seq[(Any,Int)] ={
  var res: Seq[(Any,Int)] = Seq()
    res =queue.take(number).toSeq
    queue =queue.drop(number)
  res
 }
}

enter image description here