1. 思想
- 找出数组中某个元素作为轴值,并把它放到数组右端
- 利用双指针,将数组左边全部变成
< arr[end]
,右边变成 >= arr[end]
- 记得把轴值放回分界点
- 递归调用快排,处理左边和右边的子数组
1.1 优化
- 如果数组 size 小于一定值,可以直接用插入排序
2. 算法代码
/**
* @brief 插入排序
* [begin, end]
*/
template <typename T>
void insert_sort(vector<T>& arr, size_t begin, size_t end){
if(begin>=end){
return;
}
for(size_t i=begin; i<=end; ++i){
// 从 i 一直向前交换,直到遇到边界或者前一个正序的情况
for(size_t j=i; j>begin && arr[j]<arr[j-1]; --j){
swap(arr[j-1], arr[j]);
}
}
}
/**
* @brief 快排
* [begin, end]
* 最差情况:当数组元素完全一样,每次只能完成 1 个元素的排序,需要 O(n^2)
* */
template <typename T>
void quick_sort(std::vector<T> &array, size_t begin, size_t end){
if(begin>=end){
return;
}
if(end-begin<=10){
insert_sort(array, begin, end);
return;
}
size_t idx = begin + ((end-begin)>>1);
size_t left = begin, right = end;
// 将选定的轴值放在最右,作为哨兵
swap(array[idx], array[end]);
// 将数组分为左边小于轴值,右边大于等于轴值
while(left < right){
while(left<right && array[left]<array[end]){
++left;
}
while(left<right && array[right]>=array[end]){
--right;
}
std::swap(array[left], array[right]);
}
std::swap(array[left], array[end]);
// 特别注意,size_t 情况下要避免 i==0 时减1
if(left>0)
quick_sort(array, begin, left-1);
quick_sort(array, left+1, end);
}
- 注意:
- size_t 变量使用减法的时候要小心下溢出,跟有符号整型计算的时候要小心有符号的转换(有符号自动转为无符号)
- 不足:
- 如果数组的元素全部相同,这个快排的复杂度会变成
O
(
n
2
)
O(n^2)
O(n2),要优化请看 leetcode 的题解
3. 附录
#include <vector>
using std::vector;