快速排序

经典的快速排序,先上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
public:
vector<int> sortArray(vector<int>& nums) {
if (nums.empty()) {
return nums;
}
srand(time(nullptr));
sort_array_sub(nums, 0, nums.size()-1);
return nums;
}

private:
void sort_array_sub(std::vector<int>& nums, int left, int right) {
if (left >= right) {
return;
}
int pos = rand() % (right-left+1) + left;
std::swap(nums[pos], nums[left]);
int pivot = nums[left];
int less = left;
int more = right+1;
int j = left+1;
while (j < more) {
if (nums[j] < pivot) {
less++;
std::swap(nums[less], nums[j]);
j++;
} else if (nums[j] == pivot) {
j++;
} else {
more--;
std::swap(nums[j], nums[more]);
}
}
std::swap(nums[less], nums[left]);
sort_array_sub(nums, left, less-1);
sort_array_sub(nums, more, right);
}
};

我们随机去拿到一个 pivot 点,然后将其放在当前区间的最左边。最左边记为 left,然后我们从 left+1 位置开始遍历,到 right 位置结束。

我们的这个区间可以分为三份,左边部分全部是小于 pivot 的,中间部分全是等于 pivot 的,右边部分全是大于 pivot 的。三个区间分为:[left, less-1], [less, more-1], [more, right]

开始时,less 为 left,more 为 right+1。遍历的过程中,如果遇到的值小于 pivot,则让 less++,然后交换当前这个元素和 less 对应的元素,最后继续向前。始终要想清楚,less 的左边是小于 pivot 的,所以遇到小于 pivot 的值,要让 less 自增

如果当前元素和 pivot 的值相等,那就继续向右遍历即可

如果当前元素大于 pivot 的值,让 more 的值减一,然后调用当前元素和 more 对应的元素。始终要想清楚,more 右边的一定是大于 pivot 的。所以进行调用。特别注意,不要继续向后遍历,而是应该再此遍历当前元素,因为不知道换过来的元素大小

最后遍历完之后,调用 less 和 left 的位置。因为 left 位置就是 pivot 的值。调换完之后从 less 之前就是等于 pivot 的值了。