首先是测试前准备
整体思路:生成1000个随机的字符串,如果字符串相同长度,就按字典序从小到大,否则,按照字符串长度从小到大排序,对于每一种方法,都用clock()函数记录总体时间,最后进行汇总
首先是代码准备:
#include<iostream>
#include<string>
#include<vector>
#include<time.h>
#include<algorithm>
#include<map>
#include "排序方法大全.h"
using namespace std;
const int MAXN = 1000;
const int MAXW = 100;
//随机给一组串长1-100的随机小写字母字符串,先按照串长排序,如果串长相同,则按照字典序排序
#pragma once
bool cmp(String s1, String s2);
void buddle_sort(vector<String> s);
void select_sort(vector<String> s);
void insert_sort(vector<String> s);
void insert_sort(vector<String>& s, int start, int space);
void Shell_sort(vector<String> s);
void quick_sort(vector<String>& s, int start, int end, String key);
void quick(vector<String> s);
void merge(vector<String>& s, int s1, int len1, int s2, int len2);
void merge_sort(vector<String>& s, int start, int end);
void merge_sort(vector<String> s);
void heap_sort(vector<String>& s);
void bucket_sort(vector<String>& s);
void divide_bucket(vector<String> s);
int main()
{
//随机数种子替换
srand(time(0));
vector<String> s(MAXN);
//测试冒泡排序
buddle_sort(s);
//测试选择排序
select_sort(s);
//测试插入排序
insert_sort(s);
//测试希尔排序(分治法)
Shell_sort(s);
//测试快速排序(递归,二分)
quick(s);
//测试归并排序
merge_sort(s);
//测试堆排序
heap_sort(s);
//测试桶排序
divide_bucket(s);
//测试STL:sort
Sort(s);
system("pause");
}
构造String类,它是由string字符串和一个int计算长度的构成。
String构造函数里面随机赋予了长度在1-100的随机字符的字符串给str
再重构3个运算符 > < ==
struct String
{
int length;
string str;
//冒泡排序
String()
{
length = rand() % 100 + 1;
for (int i = 0; i <= length - 1; i++)
{
char c = rand() % 26 + 'a';
char s[2] = { rand() % 26 + 'a' };
str.append(s);
}
}
String(int x)
{
length = 0;
str = "\0";
}
bool operator>(String str)
{
return (this->length == str.length) ? (this->str > str.str) : (this->length > str.length);
}
bool operator<(String str)
{
return !((this->length == str.length) ? (this->str > str.str) : (this->length > str.length));
}
bool operator==(String str)
{
return ((this->length == str.length) && (this->str == str.str));
}
};
1.冒泡排序
void buddle_sort(vector<String>s)
{
int len = s.size();
String temp(1);
time_t time1 = clock();
bool isswap = 0;
for (int i = 0; i < len - 1; i++)
{
//每次排好序以后,最大的项肯定是在最右边,所以j只需要遍历到len-i-1就可以
isswap = 0;
for (int j = 0; j < len - 1 - i; j++)
{
//先按照长度排序
if (s[j].length > s[j + 1].length)
{
isswap = 1;
temp = s[j + 1];
s[j + 1] = s[j];
s[j] = temp;
}
//再按照字典序排序
else if (s[j].length == s[j + 1].length)
{
if (s[j].str > s[j + 1].str)
{
isswap = 1;
temp = s[j + 1];
s[j + 1] = s[j];
s[j] = temp;
}
}
}
if (!isswap)//全部都排好了没有交换
break;
}
time_t time2 = clock();
cout << "冒泡排序的时间为" << time2 - time1 << "ms" << endl;
}
2.选择排序
void select_sort(vector<String>s)
{
int len = s.size();
time_t time1 = clock();
String temp;
for (int i = 0; i <= len - 1; i++)
{
//暂定最小值是第i个元素
String min = s[i];
for (int j = i; j <= len - 1; j++)
{
if (min.length > s[j].length)
{
temp = min;
min = s[j];
s[j] = temp;
}
else if (min.length == s[j].length)
{
if (min.str > s[j].str)
{
temp = min;
min = s[j];
s[j] = temp;
}
}
}
s[i] = min;//从i以后选出一个最小的,放到i位置上
}
time_t time2 = clock();
cout << "选择排序的时间为" << time2 - time1 << "ms" << endl;
}
3 插入排序
void insert_sort(vector<String>s)
{
int len = s.size();
time_t time1 = clock();
int j;
for (int i = 1; i <= len - 1; i++)
{
String temp = s[i];//空出第i个位置
for (j = i - 1; (s[j].length == temp.length) ? (s[j].str > temp.str) : (s[j].length > temp.length) && j - 1 >= 0; j--)//往左边找,直到找到一个元素它小于或者等于该元素
{
s[j + 1] = s[j];
if (j - 1 < 0)
break;
}
//停下的位置的后一个是插入的位置,当前的j位置有一个元素
s[j + 1] = temp;
}
time_t time2 = clock();
cout << "插入排序的时间为" << time2 - time1 << "ms" << endl;//时间主要节省在不用交换元素上
}
4.希尔排序
这里重构了插入排序,以传入步长和起始位置
//插入排序重构,start代表分组的位置,space代表步长(间距)
void insert_sort(vector<String>& s, int start, int space)
{
int len = s.size();
for (int i = start + space; i <= len - 1; i += space)
{
String temp = s[i];
int j = i - space;
for (j = i - space; (s[j].length == temp.length) ? (s[j].str > temp.str) : (s[j].length > temp.length); j -= space)
{
s[j + space] = s[j];
if (j - space < 0)
break;
}
s[j + space] = temp;
}
}
void Shell_sort(vector<String>s)
{
int len = s.size();
int space = len / 2;
//分组,最开始的分组为数组长度的一半,每次
time_t time1 = clock();
for (; space >= 1; space /= 2)
{
//一共有space组,每一组的起始编号为i
for (int i = 0; i <= space - 1; i++)
{
insert_sort(s, i, space);//将分好的组进行插入排序
}
}
time_t time2 = clock();
cout << "希尔排序的时间为" << time2 - time1 << "ms" << endl;
}
5.快速排序
因为有递归,所以选择了quick函数作为接口,方便计算时间(这里两个-2代表第一次初始化,但其实可以在quick函数里面初始化的,不想改了o(╥﹏╥)o)
void quick_sort(vector<String>& s, int start = -2, int end = -2, String key = 0)
{
start = (start == -2) ? (0) : (start);
end = (end == -2) ? (s.size() - 1) : (end);
int start0 = start, end0 = end;
if (start >= end)
{
return;
}
key = s[start];
while (start < end)
{
while (start < end && (s[end].length == key.length) ? (s[end].str > key.str) : (s[end].length > key.length))//end逻辑上要比key大
end--;
s[start] = s[end];
while (start < end && ((s[start].length == key.length) ? (s[start].str <= key.str) : (s[start].length <= key.length)))//start逻辑上要比key小
start++;
s[end] = s[start];
}
s[start] = key;
quick_sort(s, start0, start - 1);
quick_sort(s, start + 1, end0);
}
void quick(vector<String>s)
{
time_t time1 = clock();
quick_sort(s);
time_t time2 = clock();
cout << "快速排序的时间为" << time2 - time1 << "ms" << endl;
}
6.归并排序(真的好难)
首先定义了一个接口(因为要用到递归嘛),然后在merge_sort函数里面先分割数组,最后在归并,归并卸载了merge里面了,总体思路就这样吧
void merge(vector<String>& s, int s1, int len1, int s2, int len2)
{
//分割数组
int mid1 = s1 + len1 / 2;
int mid2 = s2 + len2 / 2;
int i1 = s1, i2 = s2, i = s1;
int flag1 = 1, flag2 = 1;
vector<String>temp;
for (; i <= s1 + len1 + len2 - 1; i++)
{
//如果左边那个有序数组的第i1个小于等于右边有序数组的第i2个
if ((((s[i1].length == s[i2].length) ? (s[i1].str <= s[i2].str) : (s[i1].length <= s[i2].length)) && flag1) || (flag2 == 0 && flag1 != 0))
{
//归并i1
temp.push_back(s[i1]);
if (i1 + 1 <= s1 + len1 - 1) i1++;
else { flag1 = 0; }
}
else if ((((s[i1].length == s[i2].length) ? (s[i1].str > s[i2].str) : (s[i1].length > s[i2].length)) && flag2) || (flag1 == 0 && flag2))
{
//归并i2
temp.push_back(s[i2]);
if (i2 + 1 <= s2 + len2 - 1) i2++;
else { flag2 = 0; }
}
}
for (i = s1; i <= s1 + len1 + len2 - 1; i++)
s[i] = temp[i - s1];
}
void merge_sort(vector<String>& s, int start, int end)
{
int len = s.size();
start = (start == -2) ? (0) : (start);
end = (end == -2) ? (s.size() - 1) : (end);
if (start < end)
{
int mid = (start + end) / 2;
merge_sort(s, start, mid);
merge_sort(s, mid + 1, end);
merge(s, start, (mid - start + 1), mid + 1, (end - mid));
}
else
{
return;
}
}
void merge_sort(vector<String>s)
{
time_t time1 = clock();
merge_sort(s, -2, -2);
time_t time2 = clock();
cout << "归并排序的时间为" << time2 - time1 << "ms" << endl;
}
7.堆排序
首先定义了一个最小堆Heap类,实现最小堆的构造和取最顶点
struct Heap
{
//将vector数组建立成最小堆
Heap(vector<String>& s)
{
int len = s.size();
for (int i = 0; i <= len - 1; i++)
{
data[size + 1] = s[i];
int index = ++size;
for (; index > 1; index /= 2)
{
if ((data[index / 2].length == data[index].length) ? (data[index / 2].str > data[index].str) : (data[index / 2].length > data[index].length))
{
String temp = data[index / 2];
data[index / 2] = data[index];
data[index] = temp;
}
}
}
}
String pop()
{
if (size)
{
String return_x = data[1];
data[1] = data[size--];
int index = 1;
for (; index * 2 <= size;)
{
if (index * 2 == size)//只有左儿子
{
if (data[index] > data[index * 2])
{
swap(data[index], data[index * 2]);
index = index * 2;
break;
}
else
{
break;
}
}
else if (data[index] > data[index * 2] || data[index] > data[index * 2 + 1])
{
if (data[index * 2] > data[index * 2 + 1])
{
swap(data[index], data[index * 2 + 1]);
index = index * 2 + 1;
}
else
{
swap(data[index], data[index * 2]);
index = index * 2;
}
}
else
break;
}
return return_x;
}
else
{
return 0;
}
}
String data[MAXN + 1] = { 0 };
int size = 0;
};
然后借助Heap类进行堆排序
void heap_sort(vector<String>& s)
{
time_t time1 = clock();
Heap* heap = new Heap(s);
for (int i = 0; i <= heap->size - 1; i++)
{
s[i] = heap->pop();
}
time_t time2 = clock();
cout << "堆排序的时间为" << time2 - time1 << "ms" << endl;
}
8.桶排序
设置字符串长length为一个桶,每+1为一个桶,用vector动态数组存储节省空间
void bucket_sort(vector<String>& s)
{
if (s.size())
quick_sort(s);
}
void divide_bucket(vector<String>s)
{
time_t time1 = clock();
int len = s.size();
vector<vector<String> > bucket(s.size() + 1);
for (int i = 0; i <= len - 1; i++)
{
//把s[i]放入指定的桶里面
bucket[s[i].length].push_back(s[i]);
}
for (int i = 0; i <= len - 1; i++)
{
bucket_sort(bucket[i]);
}
int i = 1;
s.clear();
for (int i = 1; i <= len; i++)
{
for (int j = 0; j <= (int)bucket[i].size() - 1; j++)
{
s.push_back(bucket[i][j]);
}
}
time_t time2 = clock();
cout << "桶排序的时间为" << time2 - time1 << "ms" << endl;
}
附:最后是stl里面的sort(这里采用的是降序)
bool cmp(String s1, String s2)
{
if ((s1.length == s2.length) ? (s1.str > s2.str) : (s1.length > s2.length))
{
return 1;//该交换了
}
else
{
return 0;//不交换
}
}
void Sort(vector<String>s)
{
time_t time1 = clock();
sort(s.begin(), s.end(), cmp);
time_t time2 = clock();
cout << "STL: sort时间为:" << time2 - time1 <<"ms"<< endl;
}
最终结果如下:
可能略微有不准确的地方,因为其中运用的运算符和函数调用不完全相同
仅供参考~~