选择排序通用类型实现

时间:2011-08-03 16:11:00

标签: scala

我按照我的方式实现选择和快速排序的递归版本,我试图以一种可以对任何泛型类型的列表进行排序的方式修改代码,我想假设提供的泛型类型可以转换在运行时可比较。

有没有人有关于如何做到这一点的链接,代码或教程 我正在尝试修改此特定代码

  'def main (args:Array[String]){
    val l = List(2,4,5,6,8)
    print(quickSort(l))
  }
  def quickSort(x:List[Int]):List[Int]={
    x match{
      case xh::xt =>
        {
        val (first,pivot,second) = partition(x)
        quickSort (first):::(pivot :: quickSort(second))
    }
    case Nil => {x}
  }
  }
  def partition (x:List[Int])=
  {
   val pivot =x.head
   var first:List[Int]=List ()
   var second : List[Int]=List ()

   val fun=(i:Int)=> {
     if (i<pivot)
       first=i::first
      else
         second=i::second
   } 
     x.tail.foreach(fun)
     (first,pivot,second)
   }


    enter code here

    def main (args:Array[String]){
    val l = List(2,4,5,6,8)
    print(quickSort(l))
  }
  def quickSort(x:List[Int]):List[Int]={
    x match{
      case xh::xt =>
        {
        val (first,pivot,second) = partition(x)
        quickSort (first):::(pivot :: quickSort(second))
    }
    case Nil => {x}
  }
  }
  def partition (x:List[Int])=
  {
   val pivot =x.head
   var first:List[Int]=List ()
   var second : List[Int]=List ()

   val fun=(i:Int)=> {
     if (i<pivot)
       first=i::first
      else
         second=i::second
   } 
     x.tail.foreach(fun)
     (first,pivot,second)
   } '

语言:SCALA

3 个答案:

答案 0 :(得分:3)

对于Quicksort,我将修改“Scala By Example”一书中的示例,使其更具通用性。

class Quicksort[A <% Ordered[A]] {
    def sort(a:ArraySeq[A]): ArraySeq[A] =
        if (a.length < 2) a
        else {
            val pivot = a(a.length / 2)
            sort (a filter (pivot >)) ++ (a filter (pivot == )) ++
                sort (a filter(pivot <))
        }
}

使用Int测试

    scala> val quicksort = new Quicksort[Int]
    quicksort: Quicksort[Int] = Quicksort@38ceb62f

    scala> val a = ArraySeq(5, 3, 2, 2, 1, 1, 9, 39 ,219)
    a: scala.collection.mutable.ArraySeq[Int] = ArraySeq(5, 3, 2, 2, 1, 1, 9, 39, 21
    9)

    scala> quicksort.sort(a).foreach(n=> (print(n), print (" " )))
    1 1 2 2 3 5 9 39 219

使用实现Ordered

的自定义类进行测试
scala> case class Meh(x: Int, y:Int) extends Ordered[Meh] {
     | def compare(that: Meh) = (x + y).compare(that.x + that.y)
     | }
defined class Meh

scala> val q2 = new Quicksort[Meh]
q2: Quicksort[Meh] = Quicksort@7677ce29

scala> val a3 = ArraySeq(Meh(1,1), Meh(12,1), Meh(0,1), Meh(2,2))
a3: scala.collection.mutable.ArraySeq[Meh] = ArraySeq(Meh(1,1), Meh(12,1), Meh(0
,1), Meh(2,2))

scala> q2.sort(a3)
res7: scala.collection.mutable.ArraySeq[Meh] = ArraySeq(Meh(0,1), Meh(1,1), Meh(
2,2), Meh(12,1))

答案 1 :(得分:3)

在Scala中,Java ComparatorOrdering取代(非常相似,但附带了更多有用的方法)。它们是针对几种类型(基元,字符串,bigDecimals等)实现的,您可以提供自己的实现。

然后您可以使用scala implicit让编译器为您选择正确的:

def sort[A]( lst: List[A] )( implicit ord: Ordering[A] ) = {
  ...
}

如果您使用的是预定义的订购,请致电:

sort( myLst )

并且编译器将推断出第二个参数。如果要声明自己的顺序,请在声明中使用关键字implicit。例如:

implicit val fooOrdering = new Ordering[Foo] {
  def compare( f1: Foo, f2: Foo ) = {...}
}

如果您尝试对Foo列表进行排序,它将被隐式使用。

如果您有多个相同类型的实现,您还可以显式传递正确的排序对象:

sort( myFooLst )( fooOrdering )

this post中的更多信息。

答案 2 :(得分:0)

尽管在编写Scala时,我过去喜欢函数式编程风格(通过组合器或递归)而不是命令式风格(通过变量和迭代),这个时间,针对这个特定问题,旧学校命令式嵌套循环为读者带来更简单的代码。我不认为回退到命令式样式是某些类问题的错误(例如排序算法通常会转换输入缓冲区(如过程)而不是导致新的排序类型

这是我的解决方案:

package bitspoke.algo

import scala.math.Ordered
import scala.collection.mutable.Buffer

abstract class Sorter[T <% Ordered[T]] {

  // algorithm provided by subclasses
  def sort(buffer : Buffer[T]) : Unit

  // check if the buffer is sorted
  def sorted(buffer : Buffer[T]) = buffer.isEmpty || buffer.view.zip(buffer.tail).forall { t => t._2 > t._1 }

  // swap elements in buffer
  def swap(buffer : Buffer[T], i:Int, j:Int) {
    val temp = buffer(i)
    buffer(i) = buffer(j)
    buffer(j) = temp
  }
}


class SelectionSorter[T <% Ordered[T]] extends Sorter[T] {
  def sort(buffer : Buffer[T]) : Unit = {
    for (i <- 0 until buffer.length) {
      var min = i
      for (j <- i until buffer.length) {
        if (buffer(j) < buffer(min))
          min = j
       }
       swap(buffer, i, min)
     }
  }
}

正如您所看到的,我不是使用java.lang.Comparable,而是首选scala.math.Ordered和Scala View Bounds而不是Upper Bounds。这肯定是有效的,这要归功于Rich Wrappers的许多原始类型的Scala隐式转换。

您可以按如下方式编写客户端程序:

import bitspoke.algo._
import scala.collection.mutable._

val sorter = new SelectionSorter[Int]
val buffer = ArrayBuffer(3, 0, 4, 2, 1)
sorter.sort(buffer)

assert(sorter.sorted(buffer))