This commit is contained in:
krahets
2023-02-09 04:43:12 +08:00
parent af3542e3c0
commit 4d2575be7a
18 changed files with 264 additions and 156 deletions

View File

@@ -87,10 +87,10 @@ comments: true
j := i - 1
// 内循环:将 base 插入到左边的正确位置
for j >= 0 && nums[j] > base {
nums[j+1] = nums[j] // 1. 将 nums[j] 向右移动一位
nums[j+1] = nums[j] // 1. 将 nums[j] 向右移动一位
j--
}
nums[j+1] = base // 2. 将 base 赋值到正确位置
nums[j+1] = base // 2. 将 base 赋值到正确位置
}
}
```

View File

@@ -118,7 +118,7 @@ comments: true
```go title="quick_sort.go"
/* 哨兵划分 */
func partition(nums []int, left, right int) int {
func (q *quickSort) partition(nums []int, left, right int) int {
// 以 nums[left] 作为基准数
i, j := left, right
for i < j {
@@ -128,7 +128,7 @@ comments: true
for i < j && nums[i] <= nums[left] {
i++ // 从左向右找首个大于基准数的元素
}
//元素交换
// 元素交换
nums[i], nums[j] = nums[j], nums[i]
}
// 将基准数交换至两子数组的分界线
@@ -332,16 +332,16 @@ comments: true
```go title="quick_sort.go"
/* 快速排序 */
func quickSort(nums []int, left, right int) {
func (q *quickSort) quickSort(nums []int, left, right int) {
// 子数组长度为 1 时终止递归
if left >= right {
return
}
// 哨兵划分
pivot := partition(nums, left, right)
pivot := q.partition(nums, left, right)
// 递归左子数组、右子数组
quickSort(nums, left, pivot-1)
quickSort(nums, pivot+1, right)
q.quickSort(nums, left, pivot-1)
q.quickSort(nums, pivot+1, right)
}
```
@@ -560,23 +560,38 @@ comments: true
```go title="quick_sort.go"
/* 选取三个元素的中位数 */
func medianThree(nums []int, left, mid, right int) int {
func (q *quickSortMedian) medianThree(nums []int, left, mid, right int) int {
// 使用了异或操作来简化代码(!= 在这里起到异或的作用)
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if (nums[left] < nums[mid]) != (nums[left] < nums[right]) {
return left
} else if (nums[mid] > nums[left]) != (nums[mid] > nums[right]) {
} else if (nums[mid] < nums[left]) != (nums[mid] < nums[right]) {
return mid
}
return right
}
/* 哨兵划分(三数取中值)*/
func partition(nums []int, left, right int) int {
func (q *quickSortMedian) partition(nums []int, left, right int) int {
// 以 nums[left] 作为基准数
med := medianThree(nums, left, (left+right)/2, right)
med := q.medianThree(nums, left, (left+right)/2, right)
// 将中位数交换至数组最左端
nums[left], nums[med] = nums[med], nums[left]
// 以 nums[left] 作为基准数
// 下同省略...
i, j := left, right
for i < j {
for i < j && nums[j] >= nums[left] {
j-- //从右向左找首个小于基准数的元素
}
for i < j && nums[i] <= nums[left] {
i++ //从左向右找首个大于基准数的元素
}
//元素交换
nums[i], nums[j] = nums[j], nums[i]
}
//将基准数交换至两子数组的分界线
nums[i], nums[left] = nums[left], nums[i]
return i //返回基准数的索引
}
```
@@ -792,18 +807,18 @@ comments: true
```go title="quick_sort.go"
/* 快速排序(尾递归优化)*/
func quickSort(nums []int, left, right int) {
func (q *quickSortTailCall) quickSort(nums []int, left, right int) {
// 子数组长度为 1 时终止
for left < right {
// 哨兵划分操作
pivot := partition(nums, left, right)
pivot := q.partition(nums, left, right)
// 对两个子数组中较短的那个执行快排
if pivot-left < right-pivot {
quickSort(nums, left, pivot-1) // 递归排序左子数组
q.quickSort(nums, left, pivot-1) // 递归排序左子数组
left = pivot + 1 // 剩余待排序区间为 [pivot + 1, right]
} else {
quickSort(nums, pivot+1, right) // 递归排序右子数组
right = pivot - 1 // 剩余待排序区间为 [left, pivot - 1]
q.quickSort(nums, pivot+1, right) // 递归排序右子数组
right = pivot - 1 // 剩余待排序区间为 [left, pivot - 1]
}
}
}