快速排序的基本思想
快速排序是当前最为流行的排序算法之一,其平均时间复杂度为o(nlogn),基本思想是利用分治策略,每一趟排序中选取一个元素作为中轴元素,利用该元素,将待排序列分为独立的左右两部分(左半部分都比中轴元素小,右半部分都比中轴元素大);然后对两个子序列分别递归调用快排算法,直到子序列元素个数为1,整体序列有序。具体方法:
- 每一轮排序中,选择一个数作为中轴(默认取首元素,记下标为 [ i ] ),将其复制拿出,此位置即为一个待填的“坑”;
- 从后向前扫描序列,找到第一个小于中轴的元素(下标为 [ j ] ),将其放入前面的“坑”中,此时“坑”的位置转移至 [ j ] 下标处,扫描方式改变为从前向后(由 [ i +1 ] 开始)的寻找第一个大于中轴的元素;找到后将其填入 [ j ] 位置,“坑”位转移回到当前的 [ i ] 上,然后继续改变方向…直到 i=j 时,将中轴填入 [ i ] 位置,此时 i 之前的数都比中轴小, i 之后的数都比中轴大;
- 对中轴的左右两个区间重复第二步,直到各区间少于两个元素。
代码实现
#include <iostream>
#include <time.h>
#include <stack>
#include <algorithm>
using namespace std;
/*排序方法类*/
class MySort {
public:
int n;
int* A;
//构造函数 ,便于挑选不同的排序方法
MySort(int N) {
this->n = N;
A = new int[this->n];
this->SetArray();
}
//随机初始化数组
void SetArray() {
srand(time(0));
for (int i = 0; i < n; i++) {
A[i] = rand() % 100 + 1;
}
}
//打印数组
void Print() {
for (int i = 0; i < n; i++) {
cout << A[i] << " ";
}
cout << endl;
}
//快速排序(递归法)
void quick_sort(int left, int right) { //待排数组首、尾位置
if (left < right) {
int i = left, j = right;
int mid = A[left]; //拿出首元素作为中轴x,此时A[left]为待填坑位
while (i < j) {
while (i < j && A[j] >= mid) // 从右向左找第一个小于x的数
j--;
if (i < j) //把A[j]填入A[i]中,此时坑位变为A[j],遍历方向变为从左向右
A[i++] = A[j];
while (i < j && A[i] < mid) // 从左向右找第一个大于等于x的数
i++;
if (i < j) //把A[i]填入A[j]中,改变方向同上
A[j--] = A[i];
}
A[i] = mid; //所有元素遍历后,i和j重合,中轴填入此位置
quick_sort(left, i - 1); // 递归调用
quick_sort(i + 1, right);
}
}
//快速排序(循环法)
void quickSort( int left, int right) {
stack<int> st; //用于存放当前左右两端待排下标
st.push(left);
st.push(right);
while (!st.empty()) {
int r = st.top();
st.pop();
int l = st.top();
st.pop();
int i = l,j = r;
int mid = A[(l + r) / 2];
while (i <= j) {
while (A[i] < mid) i++;
while (A[j] > mid) j--;
if (i <= j) {
swap(A[i], A[j]);
i++;
j--;
}
}
if (l < j) {
st.push(l);
st.push(j);
}
if (i < r) {
st.push(i);
st.push(r);
}
}
}
};
int main() {
//初始化数组
int N;
cout << "请输入数组长度:";
cin >> N;
MySort sort(N); //构造排序方法类
cout << endl;
cout << "获得" << N << "位随机数组:";
sort.Print();
sort.quickSort(0, N - 1);
cout << "快速排序后:";
sort.Print();
cout << endl;
return 0;
}
算法验证:
快速排序的优化思路:
- 采用更合理的基准数(中轴),从而减少递归地深度。例如:从序列的不同位置取多个数,取其中位数作中轴。
- 结合插入排序,区间在10个元素以内采用插入排序,效率更高。