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

发布于 2024-10-04 12:04:12 字数 970 浏览 2 评论 0原文

我正在尝试使用 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 包含从最小到最大的元素顺序,这是通过从所有堆栈的头部取出最小元素找到的。丹尼尔指出,我的排序将从最大到最小对我的堆栈进行排序(堆栈本身已经正确排序,最小的元素在顶部),这似乎是问题所在。

I'm trying to write a simple implementation of a patience sort, using Scala.
I've correctly managed to create the initial piles; however, my use of a priority queue to simplify output list generation is causing me a headache.

It appears that my ordering implementation is either wrong or being ignored:

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
})

The PriorityQueue appears to be ordered by (I imagine the default Stack Ordering) Stack size, rather than my Ordering.

Does anything jump out as obviously wrong?
Any help would be greatly received.
Thanks,

Edit: I didn't make it clear in the original question: I'm using Scala 2.8.1.
Edit2: I was expecting returnVal to contain a smallest-to-largest ordering of elements, found by taking the smallest element from the heads of all stacks. Daniel has pointed out that my Ordering will order my Stacks from largest-to-smallest (the stacks themselves are already ordered correctly, with smallest element on top), which appears to be the issue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

污味仙女 2024-10-11 12:04:12

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

Aren't you getting confused by the fact that the first element in the priority queue is the one with greatest value, according to the ordering? The code seems to be expecting the first element to be the one with the smallest value.

静赏你的温柔 2024-10-11 12:04:12

回答发生了什么有点困难,因为您没有包含带有输入和输出的整个程序。我的猜测是,这是由于 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)

with Scala trunk,这似乎是正确的。我应该指出 PriorityQueue 经历了一些更改,由于二进制兼容性原因,这些更改未包含在 2.8.1 中,但将在 2.9 中可用:

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

It's slightly hard to answer what's going on because you didn't include the entire program with inputs and outputs. My guess is that this is due to the old implementation of PriorityQueue in 2.8.1. The following program uses custom ordering, and fills a priority queue with a list of stacks:

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)                                                                                         
    }                                                                                                               
  }                                                                                                                 
}  

The program outputs:

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

with Scala trunk, which appears to be correct. I should point out that PriorityQueue went through some changes, which weren't included in 2.8.1 for binary compatibility reasons, but will be available in 2.9:

  • it used to be a sequence, and it's no longer a sequence - apply and update cannot be implemented meaningfully
  • calling toString or iterating over the elements will not yield heap order - the only way to obtain it is to use dequeue
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文