图解过程
对于数组s = [2, 1, 3, 0, 4, 5, 8, 7, 1]进行排序
- 将s[0]取出作为比较值val,则s[0]位置空出
- 第一步,从数组右边扫描,查询第一个比val小的, 如图1查询到s[8]
- 将s[8]放入上一步的空格中,则s[8]空出来,如图2
- 第二步,从数组左边扫描,查询第一个比val大的,如图2查询到s[2]
- 将s[2]放入上一步的空格中,则s[2]空出来,如图3
- 第三步,从数组右边扫描,查询第一个比val小的,如图3查询到s[3]
- 将s[3]放入上一步的空格中,则s[3]空出来,如图4
- ++left …
- –right …
- 直到left >= right,结束扫描,将val放入s[left],如图5
- 然后数组被分为0~left - 1, left + 1 ~ n继续递归排序
最好的情况是val每一次取到中间值,则复杂度为nlog(n)
最坏的情况是val每一次取到最小值或者最大值,则复杂度为n^2
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
#include <iomanip>
#define INF 999999999
typedef long long LL;
using namespace std;
const int MAX = 10000;
int len, arr[MAX];
void output(int *arr, int len) {
cout << "\n------\n";
for(int i = 0; i < len; ++i) {
cout << arr[i] << ' ';
}
cout << "\n------\n";
}
void quickSort(int *arr, int st, int end) { // 升序排序
if(st >= end) return;
int left = st, right = end;
int val = arr[right]; // 从左边开始寻找合适的数去填充右边的位置
while(left < right) { // 如果每次left = right = (right + left) / 2则算法复杂度为nlog(n),如果每次left = right = st或者end则复杂度为n*n
while(left < right && arr[left] < val) ++left;
arr[right] = arr[left]; // 左边的数填充了右边的位置,则需要从右边寻找合适的数去填充这个空出的位置
while(left < right && arr[right] >= val) --right;
arr[left] = arr[right];
}
arr[left] = val; // 最终剩下一个位置用来填充val,则val左边的比val小,val右边的比val大
quickSort(arr, st, left - 1);
quickSort(arr, left + 1, end);
}
int main() {
while(cin >> len) {
for(int i = 0; i < len; ++i) {
cin >> arr[i];
}
quickSort(arr, 0, len -1);
output(arr, len);
}
return 0;
}