无法将QuickSort应用于ArrayBuffer以在Scala中进行排序

时间:2013-08-25 17:52:16

标签: arrays scala functional-programming quicksort

我对Scala中的QuickSort感到困惑。根据规范,QuickSort只能应用于Array,但不能应用于ArrayBuffer。并且QuickSort将在场进行排序,即将更改原始阵列。

val intArray = Array(7,1,4,6,9)           //> intArray  : Array[Int] = Array(7, 1, 4, 6, 9)
Sorting.quickSort(intArray)
intArray.mkString("<"," and ",">")        //> res4: String = <1 and 4 and 6 and 7 and 9>

现在我无法理解为什么我不能用ArrayBuilder做同样的事情。这背后有什么理由吗?如果我想用QuickSort算法对ArrayBuilder进行排序,那么scala提供的选项是什么?感谢您的帮助。

1 个答案:

答案 0 :(得分:5)

我相信你的问题的答案可以通过检查Scala的源代码找到,以确定你可以从ArrayBuffer附带的内置函数中获得什么行为:sortWith,sortBy等。

这些函数来自定义特征“SeqLike”(您可以通过在ScalaDoc中浏览到该类来检查源代码,然后单击源代码旁边的链接:文档顶部的“Seqlike”..

无论如何,大多数与排序相关的代码都被推迟了这个函数:

def sorted[B >: A](implicit ord: Ordering[B]): Repr = {
    val len = this.length
    val arr = new ArraySeq[A](len)
    var i = 0
    for (x <- this.seq) {
      arr(i) = x
      i += 1
    }
    java.util.Arrays.sort(arr.array, ord.asInstanceOf[Ordering[Object]])
    val b = newBuilder
    b.sizeHint(len)
    for (x <- arr) b += x
    b.result()
  }

它基本上制作了数组的副本,并使用Java.util.Arrays.Sort对其进行排序。所以下一个问题就变成了,“这里的Java做什么?”我好奇,api描述:

实施说明:排序算法是Vladimir Yaroslavskiy,Jon Bentley和Joshua Bloch的Dual-Pivot Quicksort。该算法在许多数据集上提供O(n log(n))性能,导致其他快速排序降级为二次性能,并且通常比传统(单轴)Quicksort实现更快。

所以我认为基本的答案是scala在很大程度上依赖于Java内置的快速排序,并且您可以使用任何Seq函数(sorted,sortWith,sortBy),其性能优于或等于数组快速排序函数。你可能会在“复制”阶段获得一点性能,但是类只是指针(它不是克隆对象)所以除非你有数百万项,否则你不会失去很多。