package main
import "fmt"
// pdqsort 使用pdqsort算法对整数切片进行原地排序
func pdqsort(arr []int) {
const (
threshold = 16 // 阈值,当数组大小小于该值时,切换到插入排序
insertion = 8 // 插入排序的阈值
)
// 插入排序函数
insertionSort := func(begin, end int) {
for i := begin + 1; i < end; i++ {
for j := i; j > begin && arr[j] < arr[j-1]; j-- {
arr[j], arr[j-1] = arr[j-1], arr[j] // 交换元素
}
}
}
// 快速排序函数
quickSort := func(begin, end int) {
// 切换到插入排序
if end-begin <= threshold {
insertionSort(begin, end)
return
}
// 三数取中法选择主元
m := begin + (end-begin)/2
if arr[m] < arr[begin] {
arr[m], arr[begin] = arr[begin], arr[m]
}
if arr[end-1] < arr[begin] {
arr[end-1], arr[begin] = arr[begin], arr[end-1]
}
if arr[end-1] < arr[m] {
arr[end-1], arr[m] = arr[m], arr[end-1]
}
// 将主元放到倒数第二个位置
arr[m], arr[end-2] = arr[end-2], arr[m]
pivot := arr[end-2]
// 快速排序的划分过程
i, j := begin, end-2
for {
for arr[i] < pivot {
i++
}
for pivot < arr[j] {
j--
}
if i >= j {
break
}
arr[i], arr[j] = arr[j], arr[i]
i++
j--
}
arr[i], arr[end-2] = arr[end-2], arr[i]
// 递归对左右两部分进行排序
quickSort(begin, i)
quickSort(i+1, end)
}
quickSort(0, len(arr))
}
func main() {
arr := []int{9, 3, 7, 5, 1, 6, 8, 2, 4}
fmt.Println("Before sorting:", arr)
pdqsort(arr)
fmt.Println("After sorting:", arr)
}
-
在函数pdqsort中,设置了常量
threshold和insertion,分别表示切换到插入排序的阈值和插入排序的阈值。 -
函数
insertionSort是插入排序的实现,根据传入的起始位置和结束位置,对该
范围内的元素进行插入排序。
-
函数
quickSort是快速排序的实现,根据传入的起始位置和结束位置,对该范围内的元素进行快速排序。 -
在
quickSort函数中,通过三数取中法选择主元,并将主元放到倒数第二个位置。 -
接下来,使用双指针的方式进行划分过程,左指针从起始位置开始,右指针从结束位置的前一个位置开始,分别向中间移动,直到两指针相遇。
-
在划分过程中,左指针找到大于等于主元的元素,右指针找到小于等于主元的元素,然后交换这两个元素。
-
最后,递归地对左右两个划分进行快速排序。
-
在主函数
main中,定义了一个整数切片arr,并输出排序前的原始数组。 -
调用
pdqsort函数对切片进行排序。 -
最后,输出排序后的数组。