四种排序算法性能比较(冒泡、选择、快排、插入排序——数据结构)
rand()函数的边界处理
- 模块一:四类排序算法
- 模块二:问题解决
一、四类排序都采用了模板的处理方法
二、快速排序采用了递归的方式
三、利用一个函数CreateArray生成一个vector去传入四个动态数组中进行深拷贝,通过对同一数据的排序,来观测四种排序的性能比较
四、数据规模有一定的讲究,一开始我用100个数的数组去观测,结果跑出来都是0ms,因为数据规模小,几乎是在同一时间完成。所以要么扩大数据的规模,要么增倍同一排序的次数使时间更明显,这里我采用扩大数据规模的方式。
具体代码如下:
#include<iostream>
#include<vector>
#include <windows.h>
#include<map>
#include <algorithm>
using namespace std;
template<class T>
int length(T& arr);
template<typename elementType>
void maopao(elementType* a, int size);//冒泡排序 传参数组,数组长度
template<typename elementType>
void xuanze(elementType* a, int size);//选择排序 传参数组,数组长度
template<typename elementType>
void insert(elementType* a, int size);//插入排序 传参数组,数组长度
template<typename elementType>
void quick(elementType* a, int first, int last);//快速排序 传参数组,数组起始点、结束点
template<typename elementType>
int split(elementType* a, int first, int last);
template<typename elementType>
vector<elementType> CreateArray(int size);
int main() {
ULONGLONG start, end;//定义GetTickCount_t变量
int size = 32768;
int index = 0;
vector<int> array = CreateArray<int>(size);
int* a = new int[size],
* b = new int[size],
* c = new int[size],
* d = new int[size];
for (vector<int>::iterator it = array.begin(); it != array.end(); it++) {
a[index] = *it;
b[index] = *it;
c[index] = *it;
d[index] = *it;
index++;
}
start = GetTickCount64(); //开始时间
xuanze(a, size);
end = GetTickCount64(); //结束时间
cout << "选择排序所需时间 = " << ((end - start) * 1.0 ) << "ms" << endl; //输出时间(单位:s)
start = GetTickCount64();
maopao(b, size);
end = GetTickCount64(); //结束时间
cout << "冒泡排序所需时间 = " << ((end - start) * 1.0) << "ms" << endl; //输出时间(单位:s)
start = GetTickCount64();
quick(c, 0, size-1);
end = GetTickCount64(); //结束时间
cout << "快速排序所需时间 = " << ((end - start) * 1.0 ) << "ms" << endl; //输出时间(单位:s)
start = GetTickCount64();
insert(d, size);
end = GetTickCount64(); //结束时间
cout << "插入排序所需时间 = " << ((end - start) * 1.0) << "ms" << endl; //输出时间(单位:s)
return 0;
}
template<typename elementType>
void xuanze(elementType* a, int size) {
elementType temp;
for (int i = 0; i < size; i++) {
int minNumIndex = i;
for (int k = i + 1; k < size; k++) {
if (a[minNumIndex] > a[k]) {
minNumIndex = k;
}
}
if (minNumIndex != i) {
temp = a[minNumIndex];
a[minNumIndex] = a[i];
a[i] = temp;
}/*
for (int p = 0; p < size; p++) {
cout << a[p] << " ";
}
cout << endl;*/
}
}
template<typename elementType>
void insert(elementType* a, int size)
{
elementType temp;
for (int i = 0; i < size; i++) {
for (int k = i + 1; k < size; k++) {
if (a[i] > a[k]) {
temp = a[k];
a[k] = a[i];
int p = i;
while (a[p] < temp && p>1) {
a[p] = a[p - 1];
}
a[p] = temp;
}
}
/*for (int p = 0; p < size; p++) {
cout << a[p] << " ";
}
cout << endl;*/
}
}
template<typename elementType>
void quick(elementType* a, int first, int last)
{
int pos = 0;
if (first < last) {
pos = split(a, first, last);
quick(a, first, pos - 1);
quick(a, pos + 1, last);
}
}
template<typename elementType>
int split(elementType* x, int first, int last)
{
elementType pivot = x[first];
int left = first,
right = last;
while (left < right) {
while (pivot < x[right]) {
right--;
}
while (left < right && (x[left] < pivot || x[left] == pivot)) {
left++;
}
if (left < right) {
int temp = x[left];
x[left] = x[right];
x[right] = temp;
}
}
int pos = right;
x[first] = x[pos];
x[pos] = pivot;
return pos;
}
template<typename elementType>
vector<elementType> CreateArray(int size)
{
vector<elementType> Array;
map<elementType, int>ArrayMap;
typename map<elementType, int > ::iterator it;
for (int i = 0; i < size; i++) {
elementType num = rand() % size;
it = ArrayMap.find(num);
while (it != ArrayMap.end()) {
num = rand() % size;
it = ArrayMap.find(num);
}
Array.push_back(num);
ArrayMap[num] = 1;
}
return Array;
}
template<typename elementType>
void maopao(elementType* a, int size) {
bool flag = true;
for (int i = 0; i < size && flag; i++) {
flag = false;
for (int k = 1; k < size; k++) {
if (a[k] < a[k - 1]) {
elementType temp = a[k];
a[k] = a[k - 1];
a[k - 1] = temp;
flag = true;
}
}
/*for (int p = 0; p < size; p++) {
cout << a[p] << " ";
}
cout << endl;*/
}
}
template<class T>
int length(T& arr)
{
return (sizeof(arr) / sizeof(arr[0]));
}
跑出来的截图如下:
在规模相对适中的时候,不过这规模也比较小,跑出来很明显是快排性能比较好,选择次之
关于快排的一些介绍和算法内容,是比较好理解的,就是不断拆分比较左右
但是过程中一直遇到一个问题,我想测试更大规模的数据去更深一步的了解快排在遇到大数据时候的性能,比如去处理十万个数据的数据时候,它的调用栈的递归会不会显得其性能弱势起来,相比较其他的基本排序手段,反而基本的排序手段会技高一筹。
但我一直测不出来!界面卡住了!!数据只要超过32769就会界面卡住,经过不断调试,查语句,废话不多说,后来发现是rand()最大能随机产生32767的数,于是一直while出不来,实在是对很多基本的内容都不熟悉。
解决办法就是扩大我能产生的随机数的范围,可以写个函数来产生指定大范围的随机数。
因为产生的随机数不固定也没有具体要求,所以只要满足一定的数量并且不重复就够,我写的函数如下
int getRandomNum(int size)
{
return rand() * 10 + rand() % 10;
//产生一个0-326789的随机数
}
这样的随机数就足以满足100000规模不重复数字的数组样本
跑出来的时间如下:
在数据是10万的时候,快速排序算法性能不是一般的好,和其他几个排序的效率差的是千倍的效果,选择排序其次,在是插入,最后是效果最差的冒泡排序,复杂度为O(n^2).
在数据是50万的时候,结果挺震惊的.
这篇博客是我的第一篇博客,单纯用于记录一些码代码时候的注意事项,希望我的一些蠢笨的经验可以帮助到大家。如果有误,欢迎指正!