1.单路快速排序
要点
将数字小于某个标定值得归入左边
递归
每次确定标点值的位置,然后递归的确定左右数组的标定值的位置。
代码片段
package algorithms
func QuickSortOneWay(arr []int) {
n := len(arr)
quickSortOneWay(arr, 0, n-1)
}
func quickSortOneWay(arr []int, l, r int) {
if l >= r {
return
}
pos := _quickSortOneWay(arr, l, r)
quickSortOneWay(arr, l, pos-1)
quickSortOneWay(arr, pos+1, r)
}
func _quickSortOneWay(arr []int, l, r int) int {
flag := arr[l] //取某个一个值当做标定值,也就是想知道这个值应该在哪里
j := l
for k := j + 1; k <= r; k++ {
if flag > arr[k] {
j++
arr[j], arr[k] = arr[k], arr[j]
}
}
arr[j], arr[l] = arr[l], arr[j]
return j
}
代码解释
主要逻辑在_quickSortOneWay
这个函数,flag这个值其实可以用一个随机化取值得办法进行优化。
思路是随机取一个数与第一个元素交换,其余操作一样。
这个函数的遍历过程有两个快慢指针 j,k。其中k在前面探路,而j在后面记录当前小于标定值得位置。
每次找到一个小于标定值的数的时候,此时j向前移动且这个值与k交换。
如果不好理解,那么把它想象成贪吃蛇 ,每次在吃东西啊的时候头先过去,然后整个身体变长了。
2.双路快速排序
要点
从两边找到两个不符合分布的数值进行交换
递归
代码片段
func QuickSortTwoWay(arr []int) {
n := len(arr)
quickSortTwoWay(arr, 0, n-1)
}
func quickSortTwoWay(arr []int, l, r int) {
if l >= r {
return
}
pos := _quickSortTwoWay(arr, l, r)
quickSortTwoWay(arr, l, pos-1)
quickSortTwoWay(arr, pos+1, r)
}
func _quickSortTwoWay(arr []int, l, r int) int {
flag := arr[l]
i := l + 1
j := r
for {
for ; i <= r && flag > arr[i]; {//找到一个比标定值大的位置
i++
}
for ; j >= l+1 && flag < arr[j]; {//找到一个比标定值小的位置
j--
}
if i > j {
break
}
//如果i跟j分别在左右两边则交换
arr[i], arr[j] = arr[j], arr[i]
i++
j--
}
arr[j], arr[l] = arr[l], arr[j]
return j
}
代码解释
与单路排序不同的点在于这里是从左右两边开始。内部的两个循环的区间这里设置比较大,但是会提早结束所以不需要担心遍历次数多。
3.三路快速排序
要点
将数组分成3组 <标定值 =标定值 >标定值
递归
代码片段
func QuickSortThreeWay(arr []int) {
n := len(arr)
quickSortThreeWay(arr, 0, n-1)
}
func quickSortThreeWay(arr []int, l, r int) {
if l >= r {
return
}
left, right := _quickSortThreeWay(arr, l, r)
quickSortThreeWay(arr, l, left-1)
quickSortThreeWay(arr, right, r)
}
func _quickSortThreeWay(arr []int, l, r int) (left, right int) {
flag := arr[l]
left = l
right = r + 1
i := l + 1
for i < right {
if flag > arr[i] {
arr[left+1], arr[i] = arr[i], arr[left+1]
left++
i++
} else if flag < arr[i] {
right--
arr[i], arr[right] = arr[right], arr[i]
} else {
i++
}
}
arr[l], arr[left] = arr[left], arr[l]
return
}
代码解释
将小于标定值的放在左边,大于的放右边,等于的继续往前遍历