设计3题目:各种排序算法及性能分析

news2024/10/7 8:19:37

1、设计3目的

掌握各种内排序算法设计及其执行绝对时间,并对其时间性能进行比较。

2、设计3正文

2.1 实验内容

内容:编写一个程序,随机产生n个1-99的正整数序列,分别采用直接插入排序、折半插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序和二路归并排序算法对其递增排序,求出每种排序方法所需要的绝对时间。

要求:为了便于体现各类排序算法的执行时间差别,要求产生不少于50000个随机数进行测试,同时需要编写测试函数用于测试排序结果是否为递增的。

2.2 实验分析

2-1各种排序算法及性能分析功能图

本次的程序是一个对各种算法进行统计的集合,需要编写各种排序算法,在程序中需要有生成随机数的initial()函数、进行位置交换的函数swap()以及验证其正确性的test()函数、对数据及堆排序数据复制的copy()以及copy1()函数。而最为关键的则是实验中涉及算法的函数,包括了InsertSort()、BinInsertSort()、 ShellSort()、BubbleSort()、GBubbleSort()、partition()、QuickSort()、SelectSort()、sift()、HeapSort()、Merge()、MergePass()和MergeSort()函数的编写,在每种排序后有对应的计算时间所用函数,该程序的效果如图2-1各种排序算法及性能分析功能图所示。

在这些排序算法中性能最好的两种为堆排序和二路归并排序,其中堆排序是通过将无序表转化为堆,可以直接找到表中最大值或者最小值,然后将其提取出来,令剩余的记录再重建一个堆,取出次大值或者次小值,如此反复执行就可以得到一个有序序列。二路归并排序是分为两个基本的操作,一个是分,也就是把原数组划分成两个子数组的过程。另一个是治,它将两个有序数组合并成一个更大的有序数组。在归并的过程中将子表两两合并,每合并一次,就会产生一个新的且更长的有序表,重复这一步骤,直到最后只剩下一个子表,这个子表就是排好序的线性表。

堆排序通过循环对堆的元素进行排列来构造大根堆或是小根堆,该过程如图2-3所示

2-3大根堆的构建

堆排序通过两个函数HeapSort()和sift()来实现排序的功能,其中HeapSort()通过循环调用sift()来实现大根堆的构建和最大元素的交换。Sift()函数会通过比较孩子和双亲的大小来构建大根堆,并且会向下继续判断来保证后面的孩子不会被破坏大根堆的结构。

2-4二路归并排序过程


二路归并排序通过Merge()、MergePass()和MergeSort()三个函数来实现,其中MergeSort()函数循环调用MergePass()函数,然后MergePass()函数在循环调用Merge()函数来实现划分和合并的操作。其中对数组的具体操作过程如图2-4所示,先将数组划分为单个元素,然后再两两合并。

2.3 实验结果与测试

 2-3运行结果

对于运行结果进行来看,冒泡排序用时最长,改进冒泡排序相对于冒泡排序来说性能有很大的提升,堆排序用时最短。堆排序的效率与快排、归并相同,都达到了基于比较的排序算法效率的峰值(时间复杂度为O (nlogn))而除了高效之外,还只需要O (1)的辅助空间,既最高效率又最节省空间。

3、设计3总结

对于这次实验我写了直接插入排序、折半插入排序、希尔排序、冒泡排序、改进冒泡排序、快速排序、简单选择排序、堆排序和二路归并排序算法。在这么多排序算法里面我所熟知的只有冒泡排序这一个,并且我发现冒泡排序的性能要远远落后于其他排序算法。并且其中快速排序,堆排序,二路归并排序,都用到了递归的操作,并且递归算法我并不是很熟悉。这也导致了我对这些排序算法很难理解,但最终结果是好的,我学会了更多新的排序算法,还意识到算法的性能和效率对于编程的重要性,也明白了我的代码能力还很薄弱。

这些新颖的排序算法极大的开阔了我的思路,也为我以后的代码提供了更多的选择。在比较各种排序算法时,我注意到了时间复杂度和空间复杂度的重要性。不同的算法在这些方面有着显著差异,这直接影响着它们的实际应用场景。例如,快速排序和堆排序虽然在某些情况下比冒泡排序快得多,但它们的空间复杂度较高,可能会对资源有限的系统造成压力。对于一些简单的排序算法,如冒泡排序,时间复杂度为O(n^2),意味着随着数据规模的增加,算法的运行时间会急剧增长。而快速排序和堆排序的时间复杂度为O(nlogn),在许多情况下性能更优。

此外,我也意识到了算法的可读性和可维护性。虽然一些算法在性能上可能更优秀,但如果它们的代码难以理解和维护,那么在长期的项目开发中可能会带来问题。因此,在选择排序算法时,需要综合考虑多个因素。

 

4、代码

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define MaxSize 50001

void swap(int &x,int &y)//交换
{
	int tmp=x;
	x=y;
	y=tmp;
}
void initial(int R[],int low,int high)//初始化产生50001个随机数
{
	int i;
	srand((unsigned)time(NULL));
	for(i=low;i<high;i++)
	{
		R[i]=rand()%99+1;
	}
}
void copy(int R[],int R1[],int n)//用于从0开始排序
{
	for(int i=0;i<n;i++)
	  R1[i]=R[i];
}
void copy1(int R[],int R1[],int n)//用于从1开始的排序
{
	for(int i=1;i<n;i++)
	  R1[i]=R[i];
}

void test(int R[],int low,int high)//用于检验排序是否正确
{
	for(int i=low;i<high-1;i++)
	{
		if(R[i]>R[i+1]){
          printf("\t      错误\n");
		  return ;
		}
	}
    printf("\t      正确\n");
}

void InsertSort(int R[],int n)//直接插入排序
{
	int i,j;
	int tmp;
	for(i=1;i<n;i++)
	{
		if(R[i]<R[i-1])//反序时
		{
			tmp=R[i];
			j=i-1;
			do{
				R[j+1]=R[j];//关键字大于R[1]的记录后移
				j--;
			}while(j>=0&&R[j]>tmp);
			R[j+1]=tmp;
		}
	}
}

void BinInsertSort(int R[],int n)//折半插入排序,无序区中元素插到有序区里
{
	int i,j,low,high,mid;
	int tmp;
	for(i=1;i<n;i++)
	{
		if(R[i]<R[i-1])
		{
			tmp=R[i];
			low=0;high=i-1;
			while(low<=high)
			{
				mid=(low+high)/2;
				if(tmp<R[mid])
				  high=mid-1;
				else
				  low=mid+1;
			}
			for(j=i-1;j>=high+1;j--)//元素后移
			  R[j+1]=R[j];
			R[high+1]=tmp;
		}
	}
}

void ShellSort(int R[],int n)//希尔排序,每间隔d相比较,反序时交换顺序
{
	int i,j,d;
	int tmp;
	d=n/2;
	while(d>0)
	{
		for(i=d;i<n;i++)
		{
			tmp=R[i];
			j=i-d;
			while(j>=0&&tmp<R[j])
			{
				R[j+d]=R[j];
				j=j-d;
			}
			R[j+d]=tmp;
		}
		d=d/2;
	}
}

void BubbleSort(int R[],int n)//冒泡排序
{
	int i,j;
	for(i=0;i<n-1;i++)
	{
	    for(j=n-1;j>i;j--)
	    {
	    	if(R[j]<R[j-1])
		    {
			  swap(R[j],R[j-1]);
		    }
		}
	}
}

void GBubbleSort(int R[],int n)//改进冒泡排序
{
	int i,j;
	bool exchange;
	for(i=0;i<n-1;i++)
	{
		exchange=false;
	    for(j=n-1;j>i;j--)
	    {
	    	if(R[j]<R[j-1])
		    {
			  swap(R[j],R[j-1]);
			  exchange=true;
		    }
		}
		if( !exchange)
		{
			return;
		}
	}
}

int partition(int R[],int s,int t)
{
	int i=s,j=t;
	int tmp=R[i];
	while(i<j)
	{
		while(j>i&&R[j]>=tmp)
		  j--;  //从右往左扫描,找一个小于tmp的
		R[i]=R[j];//找到的R[j]放到R[i]处
		while(i<j&&R[i]<=tmp)
		  i++;//从左往右扫描,找到个大于tmp的
		R[j]=R[i];//找到的R[i]放到 R[j]处
	}
	R[i]=tmp;
	return i;
}

void QuickSort(int R[],int s,int t)//快速排序,交替所有关键字比基准小的放到前一部分 , 比基准大的放到后一部分
{
	int i;
	if(s<t)
	{
		i=partition(R,s,t);
		QuickSort(R,s,i-1);
		QuickSort(R,i+1,t);
	}
}

void SelectSort(int R[],int n)//简单选择排序,从无序区中,选择最小的关键字,放到有序区中
{
	int i,j,k;
	for(i=0;i<n-1;i++)
	{
		k=i;
		for(j=i+1;j<n;j++)
		{
			if(R[j]<R[k])
			  k=j;
		}
		if(k!=i)
		{
			swap(R[i],R[k]);
		}
	}
}

void sift(int R[],int low,int high)
{
	int i=low,j=2*i;
	int tmp=R[i];
	while(j<=high)
	{
		if(j<high&&R[j]<R[j+1])//如果右孩子比较大 ,把j指向右孩子
		  j++;
		if(tmp<R[j])//根节点小于最大孩子的关键字
		{
			R[i]=R[j];//将R[j]调到双亲位置
			i=j;
			j=2*i;
		}
		else
		  break;//如果根结点大于等于最大孩子的关键字筛选结束
	}
	R[i]=tmp;//被筛选的结点放在最终位置
}
void HeapSort(int R[],int n)//堆排序
{
	int i;
	for(i=n/2;i>=1;i--)
	{
		sift(R,i,n);
	}
	for(i=n;i>=2;i--)
	{
		swap(R[1],R[i]);//将最后一个元素与跟R[1]交换
		sift(R,1,i-1);
	}
}

void Merge(int R[],int low,int mid,int high)
{
	int *R1;
	int i=low,j=mid+1,k=0;
	R1=(int *)malloc((high-low+1)*sizeof(int));
	while(i<=mid&&j<=high)
	{
		if(R[i]<=R[j])
		{
			R1[k]=R[i];
			i++;
			k++;
		}
		else
		{
			R1[k]=R[j];
			j++;
			k++;
		}
	}
	while(i<=mid)
	{
		R1[k]=R[i];
		i++;
		k++;
	}
	while(j<=high)
	{
		R1[k]=R[j];
		j++;
		k++;
	}
	for(k=0,i=low;i<=high;k++,i++)
	   R[i]=R1[k];
	free(R1);
}

void MergePass(int R[],int length,int n)
{
	int i;
	for(i=0;i+2*length-1<n;i=i+2*length)
	  Merge(R,i,i+length-1,i+2*length-1);
	if(i+length-1<n-1)
	  Merge(R,i,i+length-1,n-1);
}

void MergeSort(int R[],int n)
{
	int length;
	for(length=1;length<n;length=2*length)
	  MergePass(R,length,n);
}

int main()
{
	int R[MaxSize],R1[MaxSize];
	printf("\n\t随机产生50000个1-99的正整数,各整数按着从小到大的顺序排序\n");
	int n=50000;
	printf("\t---------------------------------------------------------\n");
	printf("\t排序方法             用时             是否正确           \n");
	printf("\t---------------------------------------------------------\n");
	initial(R,0,n-1);
	clock_t t;

	copy(R,R1,n);
    printf("\t直接插入排序\t");
	t=clock();
	InsertSort(R1,n);
	t=clock()-t;
	printf("   %lf秒",((float)t)/CLOCKS_PER_SEC);
    test(R1,0,n-1);

	copy(R,R1,n);
    printf("\t折半插入排序\t");
	t=clock();
	BinInsertSort(R1,n);
	t=clock()-t;
	printf("   %lf秒",((float)t)/CLOCKS_PER_SEC);
    test(R1,0,n-1);


	copy(R,R1,n);
    printf("\t希尔排序\t");
	t=clock();
	ShellSort(R1,n);
	t=clock()-t;
	printf("   %lf秒",((float)t)/CLOCKS_PER_SEC);
    test(R1,0,n-1);


	copy(R,R1,n);
    printf("\t冒泡排序\t");
	t=clock();
	BubbleSort(R1,n);
	t=clock()-t;
	printf("   %lf秒",((float)t)/CLOCKS_PER_SEC);
    test(R1,0,n-1);


    copy(R,R1,n);
	printf("\t改进冒泡排序\t");
	t=clock();
	GBubbleSort(R1,n);
	t=clock()-t;
	printf("   %lf秒",((float)t)/CLOCKS_PER_SEC);
    test(R1,0,n-1);


	copy(R,R1,n);
	printf("\t快速排序\t");
	t=clock();
	QuickSort(R1,0,n-1);
	t=clock()-t;
	printf("   %lf秒",((float)t)/CLOCKS_PER_SEC);
    test(R1,0,n-1);

	copy(R,R1,n);
    printf("\t简单选择排序\t");
	t=clock();
	SelectSort(R1,n);
	t=clock()-t;
	printf("   %lf秒",((float)t)/CLOCKS_PER_SEC);
    test(R1,0,n-1);


	copy1(R,R1,n);
    printf("\t堆排序  \t");
	t=clock();
	HeapSort(R1,n);
	t=clock()-t;
	printf("   %lf秒",((float)t)/CLOCKS_PER_SEC);
    test(R1,0,n-1);


	copy(R,R1,n);
    printf("\t二路归并排序\t");
	t=clock();
	MergeSort(R1,n);
	t=clock()-t;
	printf("   %lf秒",((float)t)/CLOCKS_PER_SEC);
    test(R1,0,n-1);

	printf("\t---------------------------------------------------------\n");
	return 1;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1385335.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是MongoDB

概念&#xff1a; MongoDB 是一个文档数据库&#xff08;以 JSON 为数据模型&#xff09;&#xff0c;由 C 语言编写&#xff0c;旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 MongoDB 是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中…

白光LED驱动芯片的典型应用电路

小型白光LED驱动器LM2751 LM2751是美国国家半导体&#xff08;NS&#xff09;公司推出的一款小型白光LED驱动器&#xff0c;采用10PINLLP无铅封装&#xff0c;内置固定频率的电荷泵&#xff0c;在输入电压为2.8V&#xff5e;5.5V的情况下&#xff0c;可稳压输出4.5V或5.0V电压…

【树莓派】网线远程连接电脑和树莓派,实现SSH连接

目录 1、硬件连接&#xff1b; 2、电脑端&#xff1a; 3、查找树莓派的IP地址 4、开启树莓派的SSH接口 5、putty 6、命令行 参考文章 通过网线连接笔记本与树莓派 开启SSH和VNC功能 无显示器安装树莓派 实现&#xff1a;打开putty输入树莓派地址使用ssh方式登陆&…

【XR806开发板试用】单总线协议驱动DHT11温湿度传感器

1.昨天刚收到极速社区寄来的全志XR806开发板&#xff0c;之前用过很多全志的SOC芯片&#xff0c;但是像这种无线芯片还是第一次用。这次打算使用XR806芯片驱动一下DHT11温湿度传感器。 2.代码如下&#xff1a; #include "common/framework/platform_init.h" #inclu…

【计算机网络】TCP原理 | 可靠性机制分析(四)

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】 本专栏旨在分享学习计算机网络的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 这里写目录标题 &#x1…

软信天成:数据安全管理解决方案分享

近年来&#xff0c;随着数据环境日趋复杂多变和潜在的数据隐私泄露风险潜伏&#xff0c;如何确保企业数据安全已成为众多企业亟待面对与妥善处理的重要问题。 为了应对这一严峻的现实挑战&#xff0c;软信天成凭借专业的知识体系和丰富的实战经验积累&#xff0c;总结出了一套…

【web服务搭建实验】之nginx基础学习

目录 一、nginx的简介二、nginx安装实验虚拟主机的配置web服务器的主流实现方式-LAMP和LNMP 一、nginx的简介 Nginx是一款轻量级HTTP服务器&#xff0c;同时也是代理邮箱服务器&#xff0c;具备反向代理&#xff0c;通用代理的功能。支持多个系统&#xff0c;和不同操作系统。…

如何注释 PDF?注释PDF文件方法详情介绍

大多数使用 PDF 文档的用户都熟悉处理这种格式的文件时出现的困难。有些人仍然认为注释 PDF 的唯一方法是打印文档&#xff0c;使用笔或荧光笔然后扫描回来。 您可能需要向 PDF 添加注释、添加注释、覆盖一些文本或几何对象。经理、部门负责人在编辑公司内的合同、订单、发票或…

lvgl简介

LVGL&#xff08;Light and Versatile Graphics Library&#xff09;是一个开源的图形用户界面库&#xff0c;旨在提供轻量级、可移植、灵活和易于使用的图形用户界面解决方案。 它适用于嵌入式系统&#xff0c;可以在不同的操作系统、微控制器和图形加速器上运行。LVGL的核心…

power shell 有哪些常用命令?

PowerShell是一种命令行外壳和脚本语言&#xff0c;它基于.NET Framework并专为系统管理员设计。下面是一些常用的PowerShell命令&#xff1a; Get-Process&#xff1a;获取运行的进程列表。Get-Service&#xff1a;获取运行的服务列表。Get-EventLog&#xff1a;获取事件日志…

基于uniapp的在线课程教学系统

介绍 项目背景&#xff1a; 随着互联网的快速发展&#xff0c;在线教育已经成为一种流行的学习方式。针对这一趋势&#xff0c;我们决定开发一个基于UniApp的在线课程教学系统。该系统旨在为学生提供方便快捷的在线学习体验&#xff0c;同时也为教师提供一个高效管理课程的平台…

【java八股文】之计算机网络系列篇

1、TCP/IP和UDP模型 TCP/IP分层&#xff08;4层&#xff09;&#xff1a;应用层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层 网络的七层架构 &#xff08;7层&#xff09;&#xff1a;应用层&#xff0c;表示层&#xff0c;会话层&#xff0c;传输层&#xff…

M-A352AD10高精度三轴加速度计

一般描述 M-A352是一种三轴数字输出加速度计&#xff0c;具有超低噪声、高稳定性、低功耗等特点&#xff0c;采用了夸特的精细处理技术。. 多功能M-A352具有高精度和耐久性&#xff0c;非常适合广泛的具有挑战性的应用&#xff0c;如SHM、地震观测、工业设备的状态监测和工业…

面试题:说一下API网关的作用?企业如何应用API网关?

文章目录 一、API网关的用处1、Open API2、微服务网关3、API服务管理平台 二、API网关在企业架构中的地位三、企业中如何应用API网关四、API网关有哪些竞争方案五、API网关解决方案六、企业怎么选择API网关1、性能与可用性2、可扩展性、可维护性3、需求匹配度4、是否开源&#…

良心推荐!几款收藏的神级IDEA插件分享

本文已收录至Github&#xff0c;推荐阅读 &#x1f449; Java随想录 微信公众号&#xff1a;Java随想录 文章目录 CodeGlanceGsonFormatPOJO to JsonRainbow BracketsTranslationLombokMaven HelperAlibaba Java Code GuidelinesGenerateAllSetterMybatisXChinese (Simplified…

有哪些品牌的超声波清洗机是值得入手的?超声波清洗机推荐

作为一个既对生活品质有追求&#xff0c;又只想躺平的懒人&#xff0c;一直在努力尝试让轻松的生活少一点绊脚石&#xff0c;而其中最重要的一个&#xff0c;就是清洗眼镜清洗日常生活的一些小物件&#xff0c;讲真&#xff0c;洗这些东西有时候就跟下班回家的KPI一样。白天不累…

Linux 内核大转变:是否将迈入现代 C++ 的时代?

Linux开发者 H. Peter Anvin 在邮件列表中重启了关于 Linux内核C代码转换为C的讨论&#xff0c;并陈述了自己的观点。说之前先看一下这个话题的历史背景。 早在2018年4月1日&#xff0c;Andrew Pinski提议将 Linux 内核源码转为 C&#xff0c;在文中写道之所以引入是由于以下优…

安全生产管理平台——革新传统安全生产管理方式,重塑企业安全文化

安全生产管理在现代企业中占据着至关重要的地位。传统的安全生产管理方式虽然在一定程度上能够保障企业的生产安全&#xff0c;但随着企业规模的不断扩大和生产环境的日益复杂&#xff0c;其局限性也愈发凸显。而安全生产管理平台的出现&#xff0c;正是为了解决这一问题。 平台…

相信我,努力真的有用!

2023年对很多人来说都是异常艰辛的一年&#xff0c;大环境下的每个人都面对着或多或少的挑战&#xff0c;在这一年的时间里&#xff0c;身边的朋友陆陆续续的跳槽、创业、再就业&#xff0c;结婚&#xff0c;生娃&#xff0c;回老家&#xff0c;每个人渐渐的在时代面前或妥协或…

基于物联网设计的智能储物柜(4G+华为云IOT+微信小程序)

一、项目介绍 在游乐场、商场、景区等人流量较大的地方&#xff0c;往往存在用户需要临时存放物品的情况&#xff0c;例如行李箱、外套、购物袋等。为了满足用户的储物需求&#xff0c;并提供更加便捷的服务体验&#xff0c;当前设计了一款物联网智能储物柜。 该智能储物柜通…