【数据结构】 实验报告13 各排序算法时间性能比较

一、实验目的和要求

目的:给出一组实验来比较排序算法的时间性能
要求:
(1)时间性能
(2)实验数据应具有说服力
(3)实验结果要能以清晰的形式给出,如图、表等。
(4)算法所用时间必须是机器时间,也可以包括比较和交换元素的次数。
(5)实验分析及其结果要能以清晰的方式来描述,如数学公式或图表等。
(6)要给出实验的方案及其分析。

二、实验环境

软件环境:visual stdio 2017
硬件环境:①CPU:Intel(R)Core(TM)i7-8565U CPU @1.80Ghz
②内存:8.0GB

三、实验内容

给出一组实验来比较排序算法的时间性能

四、实验过程

4.1 任务定义和问题分析

选取若干个排序算法,对每种算法进行大量数据测试,同一规模的数据进行3次测试取平均值,最终得到若干个实验数据,进行绘图展示。

4.2 数据结构的选择和概要设计

本次实验选取直接插入排序,希尔排序,冒泡排序,快速排序,直接选择排序,堆排序,归并排序这7种算法。
分为2个大实验组,第一个大实验组为算法时间复杂度为O(n²)的算法,其中有直接插入排序,冒泡排序,直接选择排序。
第二个实验组为算法时间复杂度为O(nlogn)的算法,其中有希尔排序,快速排序,堆排序,归并排序。
4.3 详细设计
在第一个实验组中,选取规模分别为1000,5000,10000,50000,75000,100000,125000,175000,200000,250000的数据,每种数据测试三次取平均值。
在第二个实验组中,选取规模分别为10000,100000,200000,250000,500000,600000,750000,900000,1000000,10000000,25000000,30000000,40000000,50000000,60000000,75000000,100000000的数据,每种数据测试三次取平均值。在这些数据中,以1000000为分界点,分别制图。
制图采用python中的matplotlib工具,制作曲线图。
在这里插入图片描述

  • 直接插入排序
template<typename T>
void insert_sort(T array[], int n)
{
	for (int i = 1; i < n; i++)
	{
		T temp = array[i];
		int j = i - 1;
		while (array[j] > temp&&j >= 0)
			array[j + 1] = array[j--];
		array[j + 1] = temp;
	}
}
  • 希尔排序
template<typename T>
void shell_sort(T array[], int n)
{
	int d = n / 2;
	while (d > 0)
	{
		for (int i = d; i < n; i++)
		{
			T temp = array[i];
			int j = i - d;
			while (j >= 0 && temp < array[j])
			{
				array[j + d] = array[j];
				j -= d;
			}
			array[j + d] = temp;
		}
		d = d / 2;
	}
}
  • 冒泡排序
template<typename T>
void bubble_sort(T array[],int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = 0; j < n - 1 - i; j++)
		{
			if (array[j] > array[j + 1])
			{
				T temp = array[j + 1];
				array[j + 1] = array[j];
				array[j] = temp;
			}
		}
	}
}
  • 快速排序
template<typename T>
void quick_sort(T array[], int left, int right)
{
	if (left >= right) return;
	int i = left, j = right;
	T temp = array[left];
	while (i != j)
	{
		while (array[j] > temp&&j > i) j--;
		if (i < j) array[i++] = array[j];
		while (array[i] < temp&&i < j) i++;
		if (i < j) array[j--] = array[i];

	}
	array[i] = temp;
	quick_sort(array, i + 1, right);
	quick_sort(array, left, i - 1);
}
  • 直接选择排序
template<typename T>
void select_sort(T array[],int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int index = i;
		for (int j = i + 1; j < n; j++)
		{
			if (array[j] < array[index])
				index = j;
		}
		if (i != index)
		{
			T temp = array[i];
			array[i] = array[index];
			array[index] = temp;
		}
	}
}
  • 归并排序
template<typename T>
void merge_sort(T array[], int left, int right)
{
	if (left >= right) return;
	int mid = (left + right) / 2;
	merge_sort(array, left, mid);
	merge_sort(array, mid + 1, right);
	int i = left, k = left, j = mid + 1;
	while (i <= mid&&j <= right)
	{
		if (array[i] < array[j]) assist[k++] = array[i++];
		else assist[k++] = array[j++];
	}
	while (i <= mid)
		assist[k++] = array[i++];
	while (j <= right)
		assist[k++] = array[j++];
	for (int k = left; k <= right; k++)
		array[k] = assist[k];
}
  • 堆排序
template<typename T>
void swap(T arr[], int a, int b)		
{
	T temp = arr[a];
	arr[a] = arr[b];
	arr[b] = temp;
}

template<typename T>
void adjustHeap(T arr[], int i, int length)		
{
	T temp = arr[i];
	for (int k = i * 2 + 1; k < length; k = k * 2 + 1)
	{
		if (k + 1 < length&&arr[k] < arr[k + 1]) k++;
		if (arr[k] > temp)
		{
			arr[i] = arr[k];
			i = k;
		}
		else break;
	}
	arr[i] = temp;
}

template<typename T>
void heap_sort(T arr[], int length)
{
	for (int i = length / 2 - 1; i >= 0; i--)
		adjustHeap(arr, i, length);
	for (int j = length - 1; j > 0; j--)
	{
		swap(arr, 0, j);
		adjustHeap(arr, 0, j);
	}

}

五、测试及结果分析

5.1 实验数据

数据规模详见上述分析,具体数据由随机数产生,范围为0~1073283121( rand()*rand() )。

5.2 结果及分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
分析:
在图像中可以清晰地看出每种算法的时间复杂度。
先进行纵向对比,可以发现三种O(n²)的算法在数据规模达到250000时的排序用时便已全部超过20s,而O(nlogn)的算法在数据规模达到40000000时的排序用时才开始出现超过20s的现象,二者差异巨大。

故:时间复杂度为O(nlogn)的算法的时间性能远远大于O(n²)时间复杂度算法的时间性能

再进行横向对比,可以发现:时间复杂度为O(n²)的算法中,各算法对相同规模的数据的排序时间有T(冒泡排序)>T(选择排序)>T(插入排序),时间复杂度为O(nlogn)的算法中,各算法对相同规模的数据的排序时间有T(希尔排序)>T(堆排序)>T(归并排序)>T(快速排序)
故:相同时间复杂度的算法在进行相同规模数据排序时,是有差异的,这种差异随着数据规模的增加愈发明显。在O(n²)的算法中,插入排序优于选择排序,选择排序优于冒泡排序;在O(nlogn)的算法中,快速排序优于归并排序,归并排序优于堆排序,堆排序优于希尔排序

六、实验收获

在本次实验中,我通过数据,清晰地认识到了不同时间复杂度的算法在处理大规模数据时的差异,同时也认识到,时间复杂度是相对的,尽管时间复杂度的等级相同,但在运行时所耗费的时间也会有差异。本次实验启示我以后在解决问题设计算法的时候,不仅要考虑时间复杂度的等级,也需要关注实际语句的执行次数,对其优化,达到最优。

八、附录(源代码)

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
const int N = 100000 * 1000;
int a[N];
int assist[N];

template<typename T>
void print(T array[],int n)
{
	for (int i = 0; i < n; i++)
		cout << array[i] << " ";
	cout << endl;
}

template<typename T>
void insert_sort(T array[], int n)
{
	for (int i = 1; i < n; i++)
	{
		T temp = array[i];
		int j = i - 1;
		while (array[j] > temp&&j >= 0)
			array[j + 1] = array[j--];
		array[j + 1] = temp;
	}
}

template<typename T>
void shell_sort(T array[], int n)
{
	int d = n / 2;
	while (d > 0)
	{
		for (int i = d; i < n; i++)
		{
			T temp = array[i];
			int j = i - d;
			while (j >= 0 && temp < array[j])
			{
				array[j + d] = array[j];
				j -= d;
			}
			array[j + d] = temp;
		}
		d = d / 2;
	}
}

template<typename T>
void bubble_sort(T array[],int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = 0; j < n - 1 - i; j++)
		{
			if (array[j] > array[j + 1])
			{
				T temp = array[j + 1];
				array[j + 1] = array[j];
				array[j] = temp;
			}
		}
	}
}

template<typename T>
void quick_sort(T array[], int left, int right)
{
	if (left >= right) return;
	int i = left, j = right;
	T temp = array[left];
	while (i != j)
	{
		while (array[j] > temp&&j > i) j--;
		if (i < j) array[i++] = array[j];
		while (array[i] < temp&&i < j) i++;
		if (i < j) array[j--] = array[i];

	}
	array[i] = temp;
	quick_sort(array, i + 1, right);
	quick_sort(array, left, i - 1);
}

template<typename T>
void select_sort(T array[],int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int index = i;
		for (int j = i + 1; j < n; j++)
		{
			if (array[j] < array[index])
				index = j;
		}
		if (i != index)
		{
			T temp = array[i];
			array[i] = array[index];
			array[index] = temp;
		}
	}
}

template<typename T>
void merge_sort(T array[], int left, int right)
{
	if (left >= right) return;
	int mid = (left + right) / 2;
	merge_sort(array, left, mid);
	merge_sort(array, mid + 1, right);
	int i = left, k = left, j = mid + 1;
	while (i <= mid&&j <= right)
	{
		if (array[i] < array[j]) assist[k++] = array[i++];
		else assist[k++] = array[j++];
	}
	while (i <= mid)
		assist[k++] = array[i++];
	while (j <= right)
		assist[k++] = array[j++];
	for (int k = left; k <= right; k++)
		array[k] = assist[k];
}

template<typename T>
void swap(T arr[], int a, int b)		
{
	T temp = arr[a];
	arr[a] = arr[b];
	arr[b] = temp;
}

template<typename T>
void adjustHeap(T arr[], int i, int length)		
{
	T temp = arr[i];
	for (int k = i * 2 + 1; k < length; k = k * 2 + 1)
	{
		if (k + 1 < length&&arr[k] < arr[k + 1]) k++;
		if (arr[k] > temp)
		{
			arr[i] = arr[k];
			i = k;
		}
		else break;
	}
	arr[i] = temp;
}

template<typename T>
void heap_sort(T arr[], int length)
{
	for (int i = length / 2 - 1; i >= 0; i--)
		adjustHeap(arr, i, length);
	for (int j = length - 1; j > 0; j--)
	{
		swap(arr, 0, j);
		adjustHeap(arr, 0, j);
	}

}

int main()
{
	srand(time(0));
	for (int i = 0; i < N; i++)
		a[i] = rand()*rand();
	clock_t begin = clock();
	//merge_sort(a, 0, N - 1);
	heap_sort(a, N);
	clock_t end = clock();
	//print(a, N);
	cout << N << "个数据用时为" << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/RealCoder/article/details/107081459