简介:
快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
快排同冒泡都属于交换排序。不同的是,冒泡排序一次只能消除一个逆序对,而快排一次可以消除多个。
图解:
实现思路 A:
通过上图可以发现,我们通过寻找一个轴点(上图为5)使轴点两侧满足:左侧不大于轴点,右侧不小于轴点。通过分治,可以使序列中任意一点都满足上述要求。大致思路如下。
- 寻找轴点
- 划分序列,再次寻找轴点,直至到达单个序列(单个数值有序)
寻找轴点步骤:
- 随机的在序列中选取一个数m,同序列最左侧(low)值替换,从而空出low位置
- 从两个方向遍历序列(low -> hight,hight - > low)
- 若low指向的值小于m,则low右移。否则将low指向的值交换
- 另一个方向,操作相反
关于上述值交换:因为lo(以下low简称lo,height简称hi)位置已空出。则我们可以先从hi方向左移遍历。若遇到小于m的情况,则将当前值移到 lo 位置(此时hi指向的位置已空出)。然后从lo方向右移遍历。若遇到大于m的情况,则将当前值移到 hi 位置。重复此过程,直至 lo = hi。
代码示例:
#include<bits/stdc++.h>
using namespace std;
int partition(int *n, int lo, int hi){
swap(n[lo], n[lo + rand()%(hi - lo + 1)]);
int m = n[lo];
while(lo < hi){
while((lo < hi) && (n[hi] >= m))
hi--;
n[lo] = n[hi];
while((lo < hi) && (n[lo] <= m))
lo++;
n[hi] = n[lo];
}
n[lo] = m;
return lo;
}
void quick_sort(int *n, int lo, int hi){
if(lo >= hi) return;
int mi = partition(n, lo, hi);
quick_sort(n, lo, mi);
quick_sort(n, mi + 1, hi);
}
int main(){
int len = 5;
int n[len];
for(int i = 0; i < len; i++)
cin >> n[i];
quick_sort(n, 0, len - 1);
for(int i = 0; i < len; i++)
cout << n[i] << " ";
return 0;
}
实现思路 B:
思路B类似思路A,只不过构建轴点的方法不同而已。思路B每次选取序列第一个元素作为轴点,通过快排方法不断使左侧小于轴点,右侧大于轴点。
代码示例:
int partation(int *n, int lo, int hi){
int i = lo, j = hi, m = n[lo];
while(i < j){
while(i < j && n[j] >= m)
j--;
if(i < j)
swap(n[i++], n[j]);
while(i < j && n[i] <= m)
i++;
if(i < j)
swap(n[i], n[j--]);
}
return i;
}
类似还有三点选取法等,其目的都是找到合适的轴点。从而提高快排效率。