go语言版
// QuickSort 快排 核心思想:分治思想。
// 具体思路:先定基准(选择一个数作为基准数) 然后一次排序操作将基准数放到序列的"合适位置"(称为基准数归位),此时序列会被基准数分为两部分 左边序列都<=(或>=)基准数 右边序列都>=(或<=)基准数 然后再分别对左右两个序列排序(即递归)。
// 和冒泡排序一样,也需要比较和交换
// 每次排序操作最终目的都是将基准数归位
// 如何归位:假设要升序排序,且选择序列最左边的数作为基准数,然后序列左右两端各有一个哨兵,左边的哨兵往右找大于基准数的数,右边的哨兵往左找小于基准数的数,两个哨兵都找到了就交换两个数,然后继续找并交换,直到相遇,相遇后把基准数和相遇的数交换,就归位了。
// 需要注意序列两端的"哨兵"谁先开始"找",必须保证哨兵相遇时的那个元素小于(或大于,取决于具体情况)基准数
func QuickSort(a []int) {
if len(a) <= 1 {
return
}
// 1.定基准,假设选择第一个数作为基准数
base := a[0]
// 2.左右哨兵找数字,比较并交换,直到相遇
left := 0
right := len(a) - 1
for left != right {
// 先右哨兵开始找
for a[right] >= base && right > left {
right--
}
// 再左哨兵开始找
for a[left] <= base && left < right {
left++
}
// 未相遇才需要交换
if left < right {
a[left], a[right] = a[right], a[left]
}
}
// 3.基准归位
a[0], a[left] = a[left], a[0]
// 4.递归排序子序列
QuickSort(a[:left])
QuickSort(a[left+1:])
}
// QuickSort2 和QuickSort的不同在于:基准数归位后将序列分为两部分:左边都是小于基准数(QuickSort是小于等于),右边都是大于等于基准数。
// QuickSort2 只需要知道如何比较两个元素谁小于谁就行,类似sort.Interface接口的Less方法。而QuickSort需要知道如何比较两个元素是否大于等于或小于等于。
func QuickSort2(a []int) {
if len(a) <= 1 {
return
}
// 1.定基准,假设选择第一个数作为基准数
base := a[0]
// 2.左右哨兵找数字,比较并交换,直到相遇。
left := 0
right := len(a) - 1
for left != right {
// 先右哨兵开始找
for a[right] >= base && right > left {
right--
}
// 再左哨兵开始找
for (left == 0 || a[left] < base) && left < right {
left++
}
// 未相遇才需要交换
if left < right {
a[left], a[right] = a[right], a[left]
}
}
// 3.基准归位
a[0], a[left] = a[left], a[0]
// 4.递归排序子序列
QuickSort2(a[:left])
QuickSort2(a[left+1:])
}