八大排序所花时间测试序列(线性复杂度居然干不过log复杂度?)(采用的C++,结构体排序)

首先是测试前准备

整体思路:生成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;
}

最终结果如下:
在这里插入图片描述
可能略微有不准确的地方,因为其中运用的运算符和函数调用不完全相同

仅供参考~~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值