This commit is contained in:
krahets 2023-03-20 03:13:55 +08:00
parent 2ac1840c60
commit a9ff8a9e91
3 changed files with 14 additions and 2 deletions

View File

@ -29,7 +29,7 @@ comments: true
```java title="counting_sort.java"
/* 计数排序 */
// 该实现无法用于排序对象
// 简单实现,无法用于排序对象
void countingSortNaive(int[] nums) {
// 1. 统计数组最大元素 m
int m = 0;
@ -153,7 +153,7 @@ $$
```java title="counting_sort.java"
/* 计数排序 */
// 该实现可排序对象,并且是稳定排序
// 完整实现,可排序对象,并且是稳定排序
void countingSort(int[] nums) {
// 1. 统计数组最大元素 m
int m = 0;

View File

@ -286,6 +286,16 @@ comments: true
}
```
!!! question "“从右往左查找”与“从左往右查找”顺序可以交换吗?"
不行,当我们以最左端元素为基准数时,必须先“从右往左查找”再“从左往右查找”。这个结论有些反直觉,我们来剖析一下原因。
哨兵划分 `partition()` 的最后一步是交换 `nums[left]``nums[i]` ,完成交换后,基准数左边的元素都 `<=` 基准数,**这就要求最后一步交换前 `nums[left] >= nums[i]` 必须成立**。假设我们先“从左往右查找”,那么如果找不到比基准数更小的元素,**则会在 `i == j` 时跳出循环,此时可能 `nums[j] == nums[i] > nums[left]`** ;也就是说,此时最后一步交换操作会把一个比基准数更大的元素交换至数组最左端,导致哨兵划分失败。
举个例子,给定数组 `[0, 0, 0, 0, 1]` ,如果先“从左向右查找”,哨兵划分后数组为 `[1, 0, 0, 0, 0]` ,这个结果是不对的。
再往深想一步,如果我们选择 `nums[right]` 为基准数,那么正好反过来,必须先“从左往右查找”。
## 11.4.1. &nbsp; 算法流程
1. 首先,对数组执行一次「哨兵划分」,得到待排序的 **左子数组****右子数组**

View File

@ -535,6 +535,7 @@ comments: true
if (fNext != nullptr) {
fNext->prev = nullptr;
front->next = nullptr;
delete front;
}
front = fNext; // 更新头结点
// 队尾出队操作
@ -545,6 +546,7 @@ comments: true
if (rPrev != nullptr) {
rPrev->next = nullptr;
rear->prev = nullptr;
delete rear;
}
rear = rPrev; // 更新尾结点
}