Scala 实现快速排序和归并排序
def quickSort1(array: Array[Int]): Array[Int] = {
def swap(x: Int, y: Int): Unit = {
val tmp = array(x)
array(x) = array(y)
array(y) = tmp
}
def qSort(l: Int, r: Int) {
if (l < r) {
var m = l
for (i <- l + 1 to r) {
if (array(i) < array(l)) {
m += 1
swap(i, m)
}
}
swap(l, m)
qSort(l, m - 1)
qSort(m + 1, r)
}
}
qSort(0, array.length - 1)
array
}
def quickSort2(array: Array[Int]): Array[Int] = {
if(array.isEmpty) array
else {
val m = array(0)
Array.concat(
quickSort2(array.filter(_ < m)),
array.filter(_ == m),
quickSort2(array.filter(_ > m))
)
}
}
def mergeSort(list: List[Int]): List[Int] = {
def merge(l: List[Int], r: List[Int]): List[Int] =
(l, r) match {
case (Nil, _) => r
case (_, Nil) => l
case (x :: xl, y :: yr) =>
if(x < y) x :: merge(xl, r)
else y :: merge(l, yr)
}
val n = list.length / 2
if(n == 0) list
else {
val (l, r) = list splitAt n
merge(mergeSort(l), mergeSort(r))
}
}
import java.util.Date
import scala.util.Random
val array = Random.shuffle(1 to 3000).toArray
val list = array.toList
// quickSort1:
val start = new Date().getTime
val array1 = quickSort1(array.clone)
println("quickSort1: " + (new Date().getTime - start) + " ms")
// quickSort2:
val start2 = new Date().getTime
val array2 = quickSort2(array.clone)
println("quickSort2: " + (new Date().getTime - start2) + " ms")
// mergeSort:
val start3 = new Date().getTime
val list3 = mergeSort(list)
println("mergeSort: " + (new Date().getTime - start3) + " ms")
val array3 = list3.toArray
println("Equal? array1 array2 " + array1.sameElements(array2))
println("Equal? array1 array3 " + array1.sameElements(array3))
Output:
quickSort1: 23 ms
quickSort2: 61 ms
mergeSort: 24 ms
Equal? array1 array2 true
Equal? array1 array3 true
可以发现快速排序的第一种实现和归并排序的效率几乎相同。
而快速排序的第二种实现则要稍慢,但是更加简洁和直观。
观察第二种实现可以发现,它没有改变原来的数组,而是通过 \(filter\) 函数直接得到新的数组,再通过 \(concat\) 函数把它们的返回值合并起来。所以算法的效率有所降低。