算法竞赛——快速排序
快速排序算法和归并排序算法都可以用分治法的思想来解决,其区别是归并排序是等份左右划分,而快速排序则是按标兵进行划分,也不需要合并。
-
分治三步骤
- 划分问题:按标兵元素,将序列分成左右两部分,左边序列全小于等于标兵元素,右边序列全大于等于标兵元素。
- 递归求解:把左右两部分分别排序。
- 合并问题:不用合并,因为容器内元素已然有序。
算法实现
// 快速排序算法
void qSort(int *a, int lef, int righ) {
// 递归边界
if(lef > righ) {
return;
}
// 取标兵值
int centerV = a[lef + (righ - lef) / 2];
// 大于标兵值的元素放在标兵值右边
// 小于标兵值的元素放在标兵值左边
int i = lef;
int j = righ;
while(i <= j) {
// 从左往右扫描到大于标兵值的元素
for(; i <= j; i++) {
if(a[i] >= centerV) {
break;
}
}
// 从右往左扫描到小于标兵值的元素
for(; j >= i; j--) {
if(a[j] <= centerV) {
break;
}
}
// 退出条件
if(i > j) {
break;
}
// 交换
swap(a[i], a[j]);
i++;
j--;
}
// 递归求解左半
qSort(a, lef, j);
// 递归求解右半
qSort(a, i, righ);
}
测试主程序
#include <iostream>
#include <algorithm>
#include <ctime>
#include <fstream>
using namespace std;
// 快速排序算法
void qSort(int *a, int lef, int righ) {
// 递归边界
if(lef > righ) {
return;
}
// 取标兵值
int centerV = a[lef + (righ - lef) / 2];
// 大于标兵值的元素放在标兵值右边
// 小于标兵值的元素放在标兵值左边
int i = lef;
int j = righ;
while(i <= j) {
// 从左往右扫描到大于标兵值的元素
for(; i <= j; i++) {
if(a[i] >= centerV) {
break;
}
}
// 从右往左扫描到小于标兵值的元素
for(; j >= i; j--) {
if(a[j] <= centerV) {
break;
}
}
// 退出条件
if(i > j) {
break;
}
// 交换
swap(a[i], a[j]);
i++;
j--;
}
// 递归求解左半
qSort(a, lef, j);
// 递归求解右半
qSort(a, i, righ);
}
void quickSort(int *a, int n) {
qSort(a, 0, n - 1);
}
// 生成指定范围的随机数
int random(int m, int n) {
int pos, dis;
if(m == n) {
return m;
} else if(m > n) {
pos = n;
dis = m - n + 1;
return rand() % dis + pos;
} else {
pos = m;
dis = n - m + 1;
return rand() % dis + pos;
}
}
// 产生随机序列
void makeRandomSequences(int m, int n, int num) {
ofstream filerandom("quicksort.in");
// 根据时间产生相应的种子值
srand((int)time(NULL));
for(int i = 0; i < num; i++) {
filerandom << random(m, n) << " ";
// 数据量逢十换行
if(!((i + 1) % 10)) {
filerandom << endl;
}
}
filerandom.close();
}
int main() {
// // 测试数据(小量)
// int a[] = {321, 3, -3, 5, 5, 3, 5435, -11, 3423, 4432, -4421, 34432};
// int n =12;
// cout << "排序之前:";
// for(int i = 0; i < n; i++) {
// cout << a[i] << " ";
// }
// cout << endl;
//
// quickSort(a, n);
//
// cout << "排序之后:";
// for(int i = 0; i < n; i++) {
// cout << a[i] << " ";
// }
// cout << endl;
// 产生随机序列
// makeRandomSequences(-10000, 10000, 100000);
int a[200000];
int n = 0;
ifstream fileInSeq("quicksort.in");
// 打开失败
if(!fileInSeq.is_open()) {
cout << "Error opening file" << endl;
return -1;
}
// 赋值处理
while(!fileInSeq.eof()) {
fileInSeq >> a[n++];
}
fileInSeq.close();
n--;
quickSort(a, n);
ofstream fileOutSeq("quicksort.out");
for(int i = 0; i < n; i++) {
fileOutSeq << a[i] << " ";
if(!((i + 1) % 10)) {
fileOutSeq << endl;
}
}
return 0;
}