(视频学习来自哔哩哔哩)
源代码:
package main
//交换的函数
func Swap(arr []int, i, j int){
arr[i],arr[j]=arr[j],arr[i]
}
func QuickSort2(arr []int, left,right int){
if (right-left)<1{//递归结束标志,当数组只有一个时认为时有序的,按说时right=left就可以,
//但是考虑一种特殊情况,数组里只有两个数,[1,2],试着执行一下,low标志没有动,low=left,
//然后递归调用左边,区间就变成了[left, left-1],这是right-left=-1.
return
}
//以第一个作为基准(升序)
posnum := arr[left]
//定义区域
low := left //low需要++,最终使arr[left, low]都是小于基准
high := right+1 //high-- 使arr[high, right]都是大于基准的
//可以将high := right,后面的代码相继就要改
i := left+1 //i++使[low+1, i]都是等于基准的
//开始移动,大的一后面,小的移前面,等的一中间
for i<(high){//当i与 high+1重回结束循环
if arr[i]>posnum{
Swap(arr, i, high-1)
high--
}else if arr[i]<posnum{
Swap(arr, i, low+1)
i++
low++
//为什么>的时候不用i++呢:在小于的时候,交换过来的数已经做过了判断,
// 已经是比基准小的数,而大于的时候, 交换的是后面的数,后面的数没有遍历到,
//所以需要i不变,以便继续判断交换过来的数
}else{
i++//等于则跳到下一个继续判断
}
}
//不要忘了这一步,基准与low区间最后那个交换,要知道(left,low]都是比基准小的
Swap(arr,left,low)
//大小区域分别递归
QuickSort2(arr, left, low-1)
QuickSort2(arr, high, right)
}
单元测试:
import (
"fmt"
"time"
"math/rand"
"testing"
)
func TestQuickSort(t *testing.T){
//创建数组
arr := make([]int, 20,20)
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i:=0;i<20;i++{
arr[i]=r.Intn(100)
}
fmt.Println("before sort",arr)
QuickSort2(arr, 0, len(arr)-1)
fmt.Println("after sort",arr)
}
测试十组数据:
PS D:\goproject\src\go_code\排序总结> go test
before sort [75 80 88 65 25 42 60 72 69 71 31 36 62 91 56 56 63 91 4 29]
after sort [4 25 29 31 36 42 56 56 60 62 63 65 69 71 72 75 80 88 91 91]
PASS
ok go_code/排序总结 0.691s
PS D:\goproject\src\go_code\排序总结> go test
before sort [20 91 70 79 62 9 91 48 39 76 13 39 53 66 30 16 98 37 79 72]
after sort [9 13 16 20 30 37 39 39 48 53 62 66 70 72 76 79 79 91 91 98]
PASS
ok go_code/排序总结 0.422s
PS D:\goproject\src\go_code\排序总结> go test
before sort [57 28 77 57 88 35 35 13 38 53 15 47 67 36 73 70 65 83 90 45]
after sort [13 15 28 35 35 36 38 45 47 53 57 57 65 67 70 73 77 83 88 90]
PASS
ok go_code/排序总结 0.586s
PS D:\goproject\src\go_code\排序总结> go test
before sort [83 78 92 34 34 26 91 6 91 32 69 58 40 29 98 59 54 23 66 92]
after sort [6 23 26 29 32 34 34 40 54 58 59 66 69 78 83 91 91 92 92 98]
PASS
ok go_code/排序总结 0.418s
PS D:\goproject\src\go_code\排序总结> go test
before sort [44 49 23 70 21 33 46 11 88 31 92 94 81 20 32 0 20 38 56 16]
after sort [0 11 16 20 20 21 23 31 32 33 38 44 46 49 56 70 81 88 92 94]
PASS
ok go_code/排序总结 0.396s
PS D:\goproject\src\go_code\排序总结> go test
before sort [95 9 43 2 33 58 5 21 98 88 17 44 69 95 73 49 20 71 90 30]
after sort [2 5 9 17 20 21 30 33 43 44 49 58 69 71 73 88 90 95 95 98]
PASS
ok go_code/排序总结 0.419s
PS D:\goproject\src\go_code\排序总结> go test
before sort [9 55 88 95 2 42 53 47 66 55 9 42 35 40 87 14 51 52 54 3]
after sort [2 3 9 9 14 35 40 42 42 47 51 52 53 54 55 55 66 87 88 95]
PASS
ok go_code/排序总结 0.528s
PS D:\goproject\src\go_code\排序总结> go test
before sort [58 48 29 5 90 96 26 62 13 74 38 15 17 29 75 62 78 91 81 94]
after sort [5 13 15 17 26 29 29 38 48 58 62 62 74 75 78 81 90 91 94 96]
PASS
ok go_code/排序总结 0.409s
PS D:\goproject\src\go_code\排序总结> go test
before sort [80 73 25 48 21 80 24 80 40 52 61 34 26 94 13 26 89 38 14 19]
after sort [13 14 19 21 24 25 26 26 34 38 40 48 52 61 73 80 80 80 89 94]
PASS
ok go_code/排序总结 0.373s
PS D:\goproject\src\go_code\排序总结> go test
before sort [54 43 66 29 90 17 20 68 29 76 96 4 64 30 59 50 12 17 61 77]
after sort [4 12 17 17 20 29 29 30 43 50 54 59 61 64 66 68 76 77 90 96]
PASS
ok go_code/排序总结 0.688s
PS D:\goproject\src\go_code\排序总结> go test
before sort [41 20 31 16 42 89 99 11 75 26 49 36 8 35 91 85 20 59 47 66]
after sort [8 11 16 20 20 26 31 35 36 41 42 47 49 59 66 75 85 89 91 99]
PASS
ok go_code/排序总结 0.385s
PS D:\goproject\src\go_code\排序总结> go test
before sort [52 57 26 68 90 8 38 24 68 91 43 28 90 39 65 20 67 92 70 96]
after sort [8 20 24 26 28 38 39 43 52 57 65 67 68 68 70 90 90 91 92 96]
PASS
ok go_code/排序总结 0.424s
PS D:\goproject\src\go_code\排序总结> go test
before sort [62 82 58 69 15 80 87 71 68 85 5 1 25 0 53 91 32 40 56 34]
after sort [0 1 5 15 25 32 34 40 53 56 58 62 68 69 71 80 82 85 87 91]
PASS
ok go_code/排序总结 0.398s
PS D:\goproject\src\go_code\排序总结> go test
before sort [85 79 8 92 58 51 51 45 30 72 81 66 94 83 15 60 21 38 50 30]
after sort [8 15 21 30 30 38 45 50 51 51 58 60 66 72 79 81 83 85 92 94]
PASS
ok go_code/排序总结 0.411s
具体步骤在代码注释里面有,有点绕,我脑子比较笨,一早上才吃透
二分插入排序和快排可以组成一个完整的排序业务
大体 有大步:
1.因为用到递归, 首先写递归结束标志
2.确定基准,循环交换元素,交换标准:比基准小的放到[left,low]区间;比基准大的放到[high,right]区间;等于基准的在(low,high)区间
3.对[left,low],[high,right]区间重复第二步
优点:
速度快,比传统开辟内存的快排节约空间