Scala实现快速排序(算法导论)
相关内容
快速排序C++实现
Leetcode215. Kth Largest Element in an Array(基于快速排序及其划分算法)
环境
CentOS Linux release 8.1.1911 (Core)
Scala 2.13.3 (Java HotSpot(TM) 64-Bit Server VM, Java 14.0.2)
算法思路
快速排序基于分治策略,通过划分算法,递归地对左右子序列进行划分,直到划分到长度为1
的子序列回溯,经过logn
次划分,即可得到有序序列
def quickSort(start : Int, end : Int) : Unit = {
if (start < end) {
var pivot : Int = partition(start, end)
quickSort(start, pivot - 1)
quickSort(pivot + 1, end)
}
}
划分算法,每次划分算法将给定子序列以枢轴pivot
为中心,划分子序列枢轴左边的所有元素关键字小于枢轴pivot
,右边的所有元素则大于枢轴pivot
,下述算法每次设置子序列的最后一个元素为枢轴值pivotValue
,对于在子序列中其前面的所有元素,设置工作指针i
和j
作为下标索引,指针j
从左向右找到所有小于枢轴pivot
的值将其放到左边,指针i
记录找到的小于枢轴对应值的元素应该放到的左边的位置,遍历子序列中除了枢轴值pivotValue
以外所有元素,则此时i
指针的下一个位置即为枢轴的位置,因为包括i
指针指向的索引前面的所有元素都小于枢轴值,i
指针指向索引之后的元素必然大于枢轴值
def partition(start : Int, end : Int) : Int = {
// 设置工作指针
var i : Int = start - 1
var j : Int = 0
var pivotValue : Int = array(end)
// 遍历整个子序列
// 交换比枢轴大的值到左边
for (j <- start to end - 1) {
if (array(j) <= pivotValue) {
i += 1
var tmp : Int = array(i)
array(i) = array(j)
array(j) = tmp
}
}
// 将枢轴放到最终位置,即为i + 1指向的位置
// i指向索引及其前面的所有元素都小于枢轴值
var tmp : Int = array(i + 1)
array(i + 1) = array(end)
array(end) = tmp
// 返回枢轴值位置
return i + 1
}
实现代码
object QuickSort {
// 测试数据
var array : Array[Int] = Array(20, 20, 8, 5, 13, 12)
/**
* Description:
* 划分算法,选定最后一个元素为枢轴,将其放到有序的最终位置,左边的元素小于他,右边反之
* @example:
* start = 0, end = 5
* return 2
* @param: start
* 子序列起始元素索引
* @param: end
* 子序列最后元素索引
* @return: i + 1
* 枢轴位置
*/
def partition(start : Int, end : Int) : Int = {
// 设置工作指针
var i : Int = start - 1
var j : Int = 0
var pivotValue : Int = array(end)
// 遍历整个子序列
// 交换比枢轴大的值到左边
for (j <- start to end - 1) {
if (array(j) <= pivotValue) {
i += 1
var tmp : Int = array(i)
array(i) = array(j)
array(j) = tmp
}
}
// 将枢轴放到最终位置,即为i + 1指向的位置
// i指向索引及其前面的所有元素都小于枢轴值
var tmp : Int = array(i + 1)
array(i + 1) = array(end)
array(end) = tmp
// 返回枢轴值位置
return i + 1
}
/**
* Description:
* 快速排序算法,递归地划分子序列,直到划分到长度为1的子序列直接返回
* @example:
* start = 0, end = 6
* array = Array(5, 8, 12, 13, 20, 20)
* @param: start
* 子序列起始元素索引
* @param: end
* 子序列最后元素索引
* @return: unit
*/
def quickSort(start : Int, end : Int) : Unit = {
if (start < end) {
var pivot : Int = partition(start, end)
quickSort(start, pivot - 1)
quickSort(pivot + 1, end)
}
}
def main(args: Array[String]) : Unit = {
for (x <- array) {
printf("%d ", x)
}
println()
quickSort(0, array.length - 1)
for (x <- array) {
printf("%d ", x)
}
println()
}
}
伪代码
- 快速排序
QUICKSORT(A, p, r)
if (p < r)
q = PARTITION(A, p, r)
QUICKSORT(A, p, q - 1)
QUICKSORT(A, q + 1, r)
- 划分算法
PARTITION(A, p, r)
x = A[r]
i = p - 1
for j = p to r - 1
if A[j] <= x
i = i + 1
exchange A[i] with A[j]
exchange A[i + 1] with A[r]
return i + 1
测试结果
20 20 8 5 13 12
5 8 12 13 20 20
鸣谢
最后
- 上述伪代码来自算法导论
- 由于博主水平有限,不免有疏漏之处,欢迎读者随时批评指正,以免造成不必要的误解