我按照我的方式实现选择和快速排序的递归版本,我试图以一种可以对任何泛型类型的列表进行排序的方式修改代码,我想假设提供的泛型类型可以转换在运行时可比较。
有没有人有关于如何做到这一点的链接,代码或教程 我正在尝试修改此特定代码
'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
答案 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 Comparator
被Ordering取代(非常相似,但附带了更多有用的方法)。它们是针对几种类型(基元,字符串,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))