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

Posted

技术标签:

【中文标题】Scala 问题对 Stack[A] 使用 PriorityQueue 非默认排序【英文标题】:Scala problem using PriorityQueue non-default ordering for Stack[A] 【发布时间】:2010-11-29 04:12:56 【问题描述】:

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

【问题讨论】:

请提供可编译代码。这个不会编译,因为Acount 都是未知的。 是的,你是对的。我想这就是在凌晨提出问题的问题。我现在不在家,但稍后我会在我在家时编辑问题。 请明确returnVal 中的代码应该做什么——否则很难知道你的代码是否“错误”。 :-) 【参考方案1】:

您不会对优先级队列中的第一个元素是具有 最大 值的元素感到困惑吗?代码似乎期望第一个元素是具有最小值的元素。

【讨论】:

我怀疑你是对的;我必须检查我在家里使用的具体值,但是我认为是的。【参考方案2】:

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

【讨论】:

是的,发布一个例子肯定是明智的......当我回到家时,我必须检查我的具体例子发生了什么,但运行你的例子(在 2.8.1 上)给我这个: Stack(8, 15) Stack(4, 3, 2, 1, 45) Stack(3, 2, 1) Stack(-1, 0, 9, 4, 3) 这似乎只是表明初始化。堆栈的顺序已更改。完全有可能我误解了我之前得到的输出 - Daniel 指出我粘贴的代码甚至无法编译,我早上那个时候显然没有清晰的头脑!感谢您的回答!

以上是关于Scala 问题对 Stack[A] 使用 PriorityQueue 非默认排序的主要内容,如果未能解决你的问题,请参考以下文章

Scala:泛型和隐式

Scala 函数重载异常

Scala 类定义中受保护关键字的含义是啥?

全球仅10%开发者从不加班,Perl收入最高| Stack Overflow年度报告

scala-协变和逆变

Tour of Scala分章要点笔记(下)