一.基本思想
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列,其实快速排序是基于一种叫做“分治”的思想,快速排序法是目前公认的最佳排序法。
具体来说就是在data[]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间,并使左边子区间中所有记录的关键字均小于等于基准记录的关键字,右边的子区间中所有记录的关键字均大于等于基准记录的关键字, 并且接下来递归的再以同样的方式排序两个子序列,但之前的基准记录关键字将不再参与之后的排序;
分治法的基本思想
将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。
二. 例子
用实际的数据来说明原理,这样最有说服力
对data[] = 3,9,2,7,5,0,8,10
做升序排序
首先任意选取data[0] = 3
作为基准数,以这个数划分数据,使3
左边的数据全部小于3
, 3
右边的数据全部大于3
;
在初始状态下,数字3
在序列的第1
位。我们的目标是将3
挪到序列的某个合适的位置位置,假设这个位置是k
。现在就需要寻找这个k
,并且以第k
位为分界点,左边的数都小于等于3
,右边的数都大于等于3
.
可以通过以下方式做到:
设置两个变量 m = 0, n = data[].lenght - 1
分别表示data
数据的最左边和最右边;
先从
n
开始从右向左找比3
小的数,n=5 代表的数据为0
时, 0 < 3, 此时从右向左寻找完毕, 此时 m = 0, n = 5;再从
m
开始从左往右找比3
大的数,m=1, 代表的数据为9
时,9 > 3,
此时从左往右寻找完毕, 此时m = 1, n = 5;交换数据下标m = 1, n = 5代表的数据, 即交换数据
data[1] = 0
和data[5] = 9
,此时数组变成
data[] = 3,0,2,7,5,9,8,10
m = 1, n = 5再从
n
开始从右往左找比3
小的数, 当n = 2 代表的数据data[2] = 2 < 3, 此时从右往左寻找完毕, 此时m = 1, n = 2;再从
m
开始从左往右找比3
大的数, 如果m = n时还没找到 此时m = 2, n = 2; 则说明一轮排序结束, 此时需要交换m = 2时的数据data[2] = 2
和 基准数3
, 最终一轮结束后的排序呢结果是:
data[] = 2,0,3,7,5,9,8,10
这样最终通过基准数3
将data数据分为了两份, 分别是小于3
的data1[] = 2, 0
, 和大于3
的部分data2[] = 7, 5, 9, 8, 10
接着使用同样的方式分别对
data1[] = 2, 0
和data2[] = 7, 5, 9, 8, 10
进行排序操作.
三. 分析:
名称 | 时间复杂度/最好情况 | 时间复杂度/最坏情况 | 时间复杂度/平均情况 | 空间复杂度/最好情况 | 空间复杂度/最坏情况 | 稳定性 |
---|---|---|---|---|---|---|
直接插入排序 | O(nlog2n) | O(n^2) | O(nlog2n) | O(nlog2n) | O(n) | 不稳定 |
在最快及平均情况下,时间复杂度为O(nlog2n)。
最坏情况是每次挑中的 支点值不是最大就是最小,其时间复杂度为O(n2)。
在最差的情况下,空间复杂度为O(n),而最佳情况为O(log2n)
四. 代码
#include <iostream>
#include<iomanip>
using namespace std;
#define N 8//待排序元素个数
void display(int *data, int length);
void quickSort(int *data, int left, int right);
//输出函数
void display(int *data, int length)
{
for(int i = 0; i < length; i++)
{
cout<< data[i] <<" ";
}
cout<< endl;
}
//快速排序
void quickSort(int *data, int left, int right)
{
if(left > right)
{
return;
}
int m = left;
int n = right;
int pivot = data[left];//选取最左边的数据为基准数
int temp;
while(m != n)
{
//从右往左查找小于基准数的位置
while(data[n] >= pivot && m < n)
{
n--;
}
//从左往右查找大于基准数的位置
while(data[m] <= pivot && m < n)
{
m++;
}
//交换左右两边找的数据
if(m < n)
{
temp = data[m];
data[m] = data[n];
data[n] = temp;
}
}
//将基准书归位
data[left] = data[m];
data[m] = pivot;
cout<< "快速排序中: ";
display(data, N);
quickSort(data, left, m - 1); //同样的排序方式处理左边的
quickSort(data, m + 1, right); //同样的排序方式处理右边的
}
int main()
{
int data[N] = {3, 9, 2, 7, 5, 0, 8, 10};
cout<< "原始数据为:" <<endl;
display(data, N);
cout<<endl<< "快速排序:" <<endl;
//快速排序调用
quickSort(data, 0, N-1);
cout<<endl<<"快速排序后的数据:" <<endl;
display(data, N);
return 0;
}
对data[] = 3,9,2,7,5,0,8,10
做升序排序,
结果及其排序过程如图: