想要理解快速排序,首先要理解”一趟快速排序“,就是找一个记录,以它的关键字作为“枢轴”,凡其关键字小于枢轴的记录均移动至该记录之前,反之,凡关键字大于枢轴的记录均移动至该记录之后。
这样致使一趟排序之后,记录的无序序列R[s…t]将分割成两部分:R[s…i-1]和R[i+1…t],且
R[j].key(s≤j≤i-1)≤ R[i].key(枢轴 ) ≤ R[j].key(i+1≤j≤t)
一次快速排序代码下:
代码选用排序数组片段的第一个元素作为”枢轴“。
int sort(vector<int>& num, int low, int high)
{
int key = num[low];//将num[low]保存起来
while (low < high)
{
while (low < high && num[high] > key)
{
high--;
}
num[low] = num[high];
while (low < high && num[low] < key)
{
low++;
}
num[high] = num[low];
}
num[low] = key;
return low;//此时low必定等于high,返回谁都是枢轴
}
接下来就是利用分治的思想划分数组,递归求解。
代码如下:
void Qsort(vector<int>& num, int low, int high)
{
if (low < high)//只要有两个以上元素,调用一趟快速排序
{
int key = sort(num, low, high);
Qsort(num, low, key - 1);//调用一趟快速排序,不是递归
Qsort(num, key + 1, high);
}
}
完整代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int sort(vector<int>& num, int low, int high)
{
int key = num[low];//将num[low]保存起来
while (low < high)
{
while (low < high && num[high] > key)
{
high--;
}
num[low] = num[high];
while (low < high && num[low] < key)
{
low++;
}
num[high] = num[low];
}
num[low] = key;
return low;//此时low必定等于high,返回谁都是枢轴
}
void Qsort(vector<int>& num, int low, int high)
{
if (low < high)//只要有两个以上元素,调用一趟快速排序
{
int key = sort(num, low, high);
Qsort(num, low, key - 1);//调用一趟快速排序,不是递归
Qsort(num, key + 1, high);
}
}
int main() {
int b[10] = { 52, 49, 80, 36, 14, 58, 61, 97, 23, 75 };//测试用例
vector<int> a(b, b + 10);
Qsort(a, 0, 9);
for (auto i : a)
{
cout << i << endl;
}
return 0;
}
快速排序的时间复杂度分析:
最好的情况:
每次划分所取的基准都是当前无序区的"中值"记录,划分的结果是基准的左、右两个无序子区间的长度大致相等。总的关键字比较次数:O(nlogn)
最坏的情况:
每次划分选取的基准都是当前无序区中关键字最小(或最大)的记录,划分的结果是基准左边的子区间为空(或右边的子区间为空),而划分所得的另一个非空的子区间中记录数目,仅仅比划分前的无序区中记录个数减少一个。时间复杂度为O(n*n)
由于枢轴的选取具有随机性,因此快排平均时间复杂度为O(nlogn)