介绍
快速排序也是基于分治法来实现的,这在合并排序中就有说到过。它的主要实现原理就是,在数组t[n]中,选出一个数作为比较值,然后小于这个数的值放左边,大于这个数的值放右边,它则在中间;然后递归依次去操作左边和右边,如此反复,直到非空,则比较完成,而结果就已经排序好了。
实现
首先,先计算出中间值的位置:
int partition(int* a, int start, int end)
{
/// 选出数组尾数为中间值
int tail = a[end];
int i = start - 1;
/// 判断数组中哪些数小于尾数,则交换位置
for (int j = start; j <= end - 1; ++ j)
{
if (a[j] < tail)
{
++ i;
swap(a[j], a[i]);
}
}
/// 最后,把尾数和右边第一个数交换位置
swap(a[i + 1], a[end]);
/// 返回中间数的下标
return i + 1;
}
1.此算法先把尾数当成比较值,即中间值
2.然后从起始位置到结束位置遍历数组,比中间值小的放左边,比中间值大的放右边
3.然后把中间值放到中间来,即右边数第一个位置
4.然后返回中间位置
然后就是递归调用了:
/// 快速排序
/// 原理是 选出数组中的一个值,然后比这个值小的数放到左边,
/// 比这个数大的放到右边,这个数放中间,一直这样分下去,就是
/// 一个排好序的数组
void quickSort(int* a, int start, int end)
{
/// 判断数组非空
if (start < end)
{
/// 计算中间值
int mid = partition(a, start, end);
/// 左边快速排序
quickSort(a, start, mid - 1);
/// 右边快速排序
quickSort(a, mid + 1, end);
}
}
是不是很像合并排序呢? 不过此算法和合并有点不一样的地方是,它在计算中间值的时候顺便把数据已经大致排了一下,然后下面在根据左边和右边再排一次,而合并却是直接计算出中间值,然后再进行排序,最后再进行合并,而快速排序没有合并这说法。
#include <iostream>
#include <cstdint>
#include <algorithm>
using namespace std;
template<class T>
void print(T* t, int length)
{
for (int i = 0; i < length; ++ i)
{
cout << t[i] << " ";
}
cout << endl << "-----------------------" << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[10] = {10, 1, 9, 3, 5, 8, 2, 6, 4, 7};
int length = sizeof(a) / sizeof(a[0]);
print(a, length);
quickSort(a, 0, length - 1);
print(a, length);
return 0;
}
结果如下:
![quickSort-result](https://i-blog.csdnimg.cn/blog_migrate/8b5adcce0a981954a59f9d7a1fc272e2.png)
由上面的代码,大家应该也看出来了,这里选取中间值是直接选取数组的最后一个。这样做有好也有坏,好处是方便,直接选取最后一个;坏处便是,这样效率有可能很低,为什么?因为如果选取的中间数导致2边的比例是8:1或者是9:1,那这样就很影响效率了。所以,这里再提供一个随机化版本,尽量把这种因素降到最低。
int randomizedPartition(int* a, int start, int end)
{
/// 随机求出中间值 然后和末尾的值交换
int mid = (rand() % (end - start + 1)) + start;
swap(a[mid], a[end]);
return partition(a, start, end);
}
void randomizedQuickSort(int* a, int start, int end)
{
/// 判断数组非空
if (start < end)
{
/// 计算中间值
int mid = randomizedPartition(a, start, end);
/// 左边快速排序
randomizedQuickSort(a, start, mid - 1);
/// 右边快速排序
randomizedQuickSort(a, mid + 1, end);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
srand(time(NULL));
int a[10] = {10, 1, 9, 3, 5, 8, 2, 6, 4, 7};
int length = sizeof(a) / sizeof(a[0]);
print(a, length);
cout << "randomizedQuickSort:" << endl;
randomizedQuickSort(a, 0, length - 1);
print(a, length);
return 0;
}
结果如下:
![randimerQuickSort](https://i-blog.csdnimg.cn/blog_migrate/d2300dad373ea4244bd202262c39fea8.png)