C++快速排序的实现
1、QuickSort.h
/* 初始版本,升序排序 */
/* 时间复杂度:最好O(nlbn),平均O(nlbn),最坏0(n^2)
空间复杂度:O(lbn) 递归栈最大深度为[lbn] + 1
不稳定:情况基于每次划分选择的主元。随机化快排得到理论最坏情况的可能性仅为1/(2^n)
/*
* 快排思想:
* 1. 随机选取一个主元作为基准,从待排序记录序列左右两端开始,逐渐向中间靠拢,交替与主元比较、交换
* 左侧记录大于主元则交换,右侧记录大于主元则交换,交换后向中间靠拢
* 最后,主元到达它的最终位置
* 2. 对主元左右两个区域重复上述快速排序过程,结果分别让左右两个区域中的主元到达它们的最终位置
* 同时将待排序记录序列分成更小的待排序区域,再次对每个区域进行一趟快速排序,直到每个区域只有一个记录为止
*/
#ifndef QUICKSORT_H
#define QUICKSORT_H
#include <stdlib.h>
/* 从0开始,n为数组大小 */
int Partition(int arr[], int n)
{
int pos = 0 + rand() % n; // 随机选取主元 a + rand() % b = [a, b) 随机一个整数
int main = arr[pos]; // 记录主元的值,后面将主元放置于最中间
int low = 0, high = n - 1;
std::swap(arr[0], arr[pos]); /* TODO :将主元跟最低位置的元素交换,这一步很重要 */
while(low < high) // 比较完毕之后,主元应该放置到的位置就是low == high,因为low == high时比较完毕,左边的比主元小,右边的比主元大,这就是主元所处的位置。
{
/* 必须从右边开始,因为要确保low == high时,arr[low]的值必须小于主元。即保证low == high右侧的元素大于等于主元。
若从左边开始,则应先将主元与最高位置的元素交换 */
while(low < high && arr[high] >= main) // 找到右边区域比主元小的数
--high;
while(low < high && arr[low] <= main) // 找到左边区域比主元大的数
++low;
if(low < high)
std::swap(arr[low], arr[high]); // 交换值
}
arr[0] = arr[low]; /* arr[0]保存的是主元的值,在循环中没有经过交换,而arr[low]的值小于主元,所以要把arr[low]放到主元左边 */
arr[low] = main; // 再把主元归位,记住此处 low == high
return low;
}
void QuickSort(int arr[], int n)
{
if(n <= 1)
return;
if(n > 1)
{
int p = Partition(arr, n); // 选取一个主元,交换左右区域数据
/* 去掉注释可以查看快排内部过程 */
// std::cout << std::endl;
// for(int i = 0; i < p; ++i)
// std::cout << arr[i] << " ";
// std::cout << "**" << arr[p] << "** ";
// for(int i = 0; i < n - p - 1; ++i)
// std::cout << arr[p + 1 + i] << " ";
QuickSort(arr, p); // 对左边区域进行快速排序
QuickSort(arr + p + 1, n - p - 1); // 对右边区域进行快速排序
}
}
#endif // QUICKSORT_H
2、main.cpp
#include <iostream>
#include <stdlib.h>
#include "QuickSort.h"
#define MAX 10 // 随机数的最大数
#define MIN 1 // 随机数的最小数
#define MAXSIZE 10 // 数组大小
#define SORTTIMES 100 // 随机生成数组并进行排序的次数
int main(int argc, char *argv[])
{
int arr[MAXSIZE];
int i = SORTTIMES;
while(i--){
for(int i = 0; i < MAXSIZE; ++i)
{
arr[i] = (MIN + (int)MAX * rand() / (RAND_MAX + 1)); // 生成随机数组
std::cout << arr[i] << " "; // TODO : 输出生成的随机数,可注释掉
}
QuickSort(arr, MAXSIZE); // 排序
std::cout << "\t ==> \t";
for(int i = 0; i < MAXSIZE; ++i)
std::cout << arr[i] << " ";
std::cout << std::endl;
}
}
测试结果: