前言
我们之前介绍的桶排序利用数组排序,虽然操作简便,时间性能上也很是友好,O(M+N),然而却有不少致命的缺陷,比如浪费空间。而冒泡排序虽然解决了空间上的浪费,但是双重循环下的两两互换,在时间性能上却是得不偿失,O(N^2),空有名字的浪漫,却是一无是处。
那么是否有一种时间和空间上的双重友好呢?显然是有的,这么我们简单的介绍一下,Charles Antony Richard Hoare先生在1960年提出的快速排序。
一、快速排序
首先随便给出我们要排序的一组数值:
如:5、3、8、9、6、1、2、7、4、10
我们这边以最左边的值5设置为基准数,就是一个随便给的名字,你叫它张三也可以。以基准数为轴,将这些数值化为两部分,左边都小于基准数,而右边都大于基准数。
怎么操作呢?对值的操作归根结底还是互换。这边我们给出 i 和 j 两个下标,分别指向最左边和最右边。基准数在最左边,我们就从最右边 j 开始移动,再从左边 i 移动。这边可以自己推演一下,如果是同端移动,即左边开始移动,会出现问题。
j 所指的值,若大于5,则j–;
然后换i移动,i所指的值,若小于5,则i++;
while (a[j] >= a[left] && i < j)
{
j--;
}
while (a[i] <= a[left] && i < j)
{
i++;
}
不然则就兑换值,继续移动。
int t = 0;
t = a[i];
a[i] = a[j];
a[j] = t;
直至i、j同时指向相同的数。这时则与基准数兑换,即可完成以基准数未轴的二分。
a[left] = a[i];
a[i] = temp;
进而以此类推,采用递归的方式进行划分。
quickSort(a, left, i - 1);
quickSort(a, i+1, right);
这里我们提供一次划分的动向过程:
原:5、3、8、9、6、1、2、7、4、10
①:5、3、4、9、6、1、2、7、8、10
②:5、3、4、2、6、1、9、7、8、10
③:5、3、4、2、1、6、9、7、8、10
④:1、3、4、2、5、6、9、7、8、10
这时就完成了第一次的二分。之后,一分为二继续排序划分,直至完成排序。
二、快速排序源码
#include <iostream>
using namespace std;
void quickSort(int a[],int left, int right)
{
if (left > right)
{
return;
}
int i = left, j = right, temp = a[left];
while (i != j)
{
while (a[j] >= a[left] && i < j)
{
j--;
}
while (a[i] <= a[left] && i < j)
{
i++;
}
int t = 0;
t = a[i];
a[i] = a[j];
a[j] = t;
}
a[left] = a[i];
a[i] = temp;
quickSort(a, left, i - 1);
quickSort(a, i+1, right);
}
int main()
{
cout << "排序的个数:";
int sortLenght = 0;
cin >> sortLenght;
int* a = new int[sortLenght];
cout << "输入要排序的数值:" << endl;
for (int i = 0; i < sortLenght; i++)
{
cout << "第" << i + 1 << "个数:";
cin >> a[i];
}
cout << "未排序的序列:";
for (int i = 0; i < sortLenght; i++)
{
cout << a[i] << " ";
}
cout << endl;
quickSort(a, 0, sortLenght - 1);
cout << "排序完的序列:";
for (int i = 0; i < sortLenght; i++)
{
cout << a[i] << " ";
}
return 0;
}