常用排序算法以及算法性能测试(完整C/C++代码实现)

排序算法性能的比较

注: 由于只是测试算法性能, 所以不会对排序算法做深入讲解, 在随后的时间将会推出排序的详细讲解

问题需求分析

排序算法经过了很长时间的演变,产生了很多种不同的方法。每种算法主要针对不同的数列进行排序,这些排序算法具有各自的利弊,并且应用的场景各自不同,为了针对不同的场景选出最合适的排序算法,接下来将使用大量随机数列,以及不同的数据场景对不同的排序算法进行比较,最终找出排序算法各自的优缺点以及不同应用的场景。

数据结构定义

选用8种不同乱序的数列,每种数列使用6组不同的数列进行测试,每组数列大小在500左右(若数据量太小不能明显测试,将会修改为更大的数据)。

测试系统功能设计及排序算法原理概述

随机数产生函数:总共有8中乱序数据, 其中两组是属于正序与反序状态, 这两种状态直接通过排序函数获得, 剩余6种状态采用的方法是通过设定随机数范围n,m控制随机数整体体现一个升序或者是降序的状态, 但是局部出现的就是部分无序, 所以就可以限定数列有序的状态

插入排序: 1.获得一个数, 就去数组从数组末尾比较直达找这个数合适的位置, 2.重复1中的步骤, 直到所有数在数组中都没找到一个合适的位置.

希尔排序: 原理与插入排序的效果一样, 插入排序每次从数组中选的数总是依次选, 选取的数间隔是1, 而希尔排序每次总是按照一定的间隔选取数, 就比如第一次选n/2, 第二次选n/4, 直到选间隔数为1, 此时的希尔排序就只是单纯的插入排序, 但是与插入排序不同的, 当处理大量数据且数据一定程度上有序, 相比于插入排序, 希尔排序的速度将会是极大的提升.

冒泡排序: 1.遍历整个数组, 相邻之间的数不断比较, 直到数组中最大(最小)的数移动到数组的末尾(开头). 2.重复1中步骤, 直到所有数都能在数组中(局部)变为最大或最小的数.

快速排序: 1.遍历数组, 从右往左, 找比基准元素小的元素A, 同时从左往右, 找比基准元素大的元素B, 若找到则交换A,B的位置(此时i,j下标还没碰头), 当i,j碰头的时候, i,j对应的下标就是基准元素的位置, 此时将基准元素与i,j下标的元素交换, 这样的一轮循环就完成了一个元素的寻找. 2.递归往下寻找, 以刚才找到的元素位置作为分界线, 二分再次进行查找, 重复1中步骤.(1中的查找方式, 为步骤2二分操作打下基础, 每次基准元素(此时的基准元素已经找到了合适的位置)左边的元素总是会比右边的元素小)
选择排序: 1.遍历数组, 找到数组中最大(最小)元素的位置, 然后交换该元素与数组末尾(开头)的元素, 一趟遍历就能找到一个元素的合适位置. 2.重复1中步骤, 直达所有元素都能找到自己合适的位置.

堆排序: 1.根据父节点与左右子树下标的关系(左节点:2i,右节点:2i+1)遍历数组, 比较左右节点, 父节点之间的大小关系, 3个元素中找出最小(最大)的元素作为父节点(存在父节点与子节点之间顺序的交换), 此时局部的子树就构建成小顶堆(大顶堆). 2.进行size/2次循环执行步骤1, 使得能构建大顶堆(小顶堆). 3.在构建出大顶堆(小顶堆)的基础上, 拿出最大数(最小数)(这里的做法是, 将root处的值与数组末尾的值(叶子节点, 下标j–, 排好序的数列就不能打乱哦)交换), 剩下数再进行1中步骤, 此处类似于选择, 在构建好的大顶堆(小顶堆)中拿出最大(最小)值. 4.重复3中步骤, 直到所有数都找出来.

函数调用图

在这里插入图片描述

测试样例数据:

Level取值如下(5,6,7属于整体逆序的状态):1:正序; 2:有点乱; 3:乱的比较多; 4:完全随机; 5:乱的比较多; 6:有点乱; 7:逆序 ;8:正序 ;测试数据量为400.

在这里插入图片描述

结论分析

从上面这个表来看, 当数量已经是正序的时候采用冒泡排序是最快; 在逆序的状态下还是采用快速排序, 若要求数列稳定性, 应该采用选择排序; 在整体处于正序的时候使用冒泡, 选择排序都是有优势的; 而整体处于逆序的时候还是选择排序和快速排序; 当数列完全逆序的时候, 选择快速排序是最好的; 从上面整体来看, 快排的平均时间复杂度最低, 堆排序平均时间复杂度最高, 冒泡, 插入, 选择时间复杂度差不多, 而希尔排序在大量数据的时候优于插入排序.

调试代码存在的问题

1.构建随机函数的时候, 由于n, m参数没有控制好, 导致出现的数列具有一定的误差, 这个问题只用通过大量的参数测试, 直到找出最合适的n与m.
2.进行希尔排序的时候, 我选用的间隔是 n/=2, 每次选取的间隔数自动缩短为1/2, 但是也导致了一个问题就是, 到最后n的值可能是0, 由此导致希尔排序出现死循环, 这个问题调试了好一会, 才发现, 在这一次的调试中, 更加深入理解了希尔排序的真谛, 其他排序也一样,写的过程中, 也存在许多问题, 大部分问题最终还是体现在对排序算法的不熟悉导致, 由于没有弄清楚排序的真正机制, 所以也就导致太多不应该犯的错误.

完整代码

#include<iostream>
#include <stdlib.h> 
#include <time.h>  
using namespace std;  
const long Size=400;
//所有元素的0号位都是临时元素 
void show(int a[],int size){for(int i=1;i<size;i++){cout<<a[i]<<" ";if((i+1)%20==0)cout<<endl;}
}//插入排序
void insertSort(int a[],int size, int &cs, int &ss){int i,j;for(i=1;i<size;i++){ a[0]=a[i]; j=i-1;while(true){//临时元素从数列末尾-1进行比较,直到遇到比他小的停止 ++cs;if(a[0]<a[j]){//移动过程中出现交换 ++ss;a[j+1]=a[j--];}else break;	}//找到比他小的元素,进行交换++ss; a[j+1]=a[0];}
}//希尔排序
void shellSort(int a[],int size, int &cs, int &ss){int i,j,dk=size/25;while(dk > 0){dk /= 2;if(dk > 0 && dk < 10) dk = 1;for(i = dk; i < size; i++){++cs; if(a[i] < a[i-dk]){a[0] = a[i];j = i-dk;++cs; while(a[0] < a[j]){++ss; a[j+dk] = a[j];j -= dk;}++ss; a[j+dk] = a[0];}}}
}//冒泡排序
void bubbleSort(int a[],int size, int &cs, int &ss){int flag=0;for(int i=1;i<size;i++){flag=1;for(int j=1;j<size-i;j++){++cs; if(a[j]>a[j+1]){++ss; a[0]=a[j];a[j]=a[j+1];a[j+1]=a[0];flag=0;}}if(flag==1)break;}
}//快速排序
void quickSort(int a[],int l,int r, int &cs, int &ss){if(l>r)return; int i=l,j=r,t;a[0]=a[l];++cs; while(i!=j){++cs; while(a[0]<=a[j]&&i<j){j--;} ++cs; while(a[0]>=a[i]&&i<j){i++;}++cs;if(i<j){++ss; t=a[i];a[i]=a[j];a[j]=t;//左右两边的值交换 }}++ss;a[l]=a[i];a[i]=a[0];//基数的交换 quickSort(a,l,i-1, cs, ss);quickSort(a,i+1,r, cs, ss);
}//选择排序
void selectSort(int a[],int size, int &cs, int &ss){int i,j,k;for(i=1;i<size;i++){k=i;for(j=i;j<size;j++){++cs; if(a[k]>a[j])k=j; }++cs; if(k!=i){++ss; a[0]=a[k];a[k]=a[i];a[i]=a[0];}}
}
//建堆操作
void heapAdjust(int a[],int i,int n, int &cs, int &ss){//建立大顶堆 int temp;//将局部最小的树变为堆 temp=a[i];for(int j=i*2;j<=n;j++){//for循环主要针对局部子树的调整,//将左右子树中大值往前调整++cs;if(j<n&&a[j]<a[j+1])j++;//左右子树进行比较 ++cs;if(temp>=a[j])break;++ss;a[i]=a[j];//与根节点进行交换 i=j;//i原本为j的root,现在j向子树深入,root进行改变//i变为j }++ss;a[i]=temp;
}
//堆排序
void heapSort(int a[],int size, int &cs, int &ss){for(int i=size/2;i>0;i--)heapAdjust(a,i,size, cs, ss);for(int j=size;j>1;j--){//每调整一下,就将root与最远的叶子进行交换//此处的root为最大值 ++ss;a[0]=a[1];a[1]=a[j];a[j]=a[0];heapAdjust(a,1,j-1, cs, ss);}
}
//生成随机数,level代表乱序程度 
控制m, n取值范围, 可有效控制随机数混乱程度
1 5个数中取随机数
2 10 中取随机数
3 完全随机
4 完全随机
5 10个取随机数 
6 5个取随机数 
7 逆序 
**/
void createSrand(int a[],int size, int level){int m, n;if(level < 5){m = 0; n = 50;}else{m = 3951; n = 4001;}srand((unsigned)time(NULL)); // rand()%(n-m+1)+m, [m,n]范围内的随机数 for(int i= 0; i < size;i++ ){if(level == 1){m += 10;n += 10;}else if(level == 2){m += 5;n += 7;}else if(level == 4){m = 0;n = 4001;}else if(level == 4){m = 0;n = 4001;}else if(level == 5){m -= 5;n -= 7;}else if(level == 6){m -= 10;n -= 10;}else if(level == 7){int flag=0;for(int i=1;i<size;i++){flag=1;for(int j=1;j<size-i;j++){if(a[j]<a[j+1]){a[0]=a[j];a[j]=a[j+1];a[j+1]=a[0];flag=0;}}if(flag==1)break;}
//			show(a, size);return;}else if(level == 8){int i = 0;quickSort(a, 1, Size-1, i, i);
//			show(a, size);return;}a[i]=rand()%(n-m+1)+m;}
//	show(a, size);
}//性能测试函数
void testLevel(int a[], int size){int cs, ss;for(int i = 1; i < 9; i++){cs = 0, ss = 0;createSrand(a, size, i);cout<<"Level="<<i<<" insertSort:";insertSort(a,Size,cs,ss);cout<<"  cs="<<cs<<"  ss="<<ss<<endl;cout<<"-----------------------------------------------------------\n"<<endl;cs = 0, ss = 0;createSrand(a,Size,i);cout<<"Level="<<i<<" shellSort:";shellSort(a,Size,cs,ss);cout<<"  cs="<<cs<<"  ss="<<ss<<endl;cout<<"-----------------------------------------------------------\n"<<endl;cs = 0, ss = 0;createSrand(a,Size,i);cout<<"Level="<<i<<" bubbleSort:";bubbleSort(a,Size,cs,ss);cout<<"  cs="<<cs<<"  ss="<<ss<<endl;cout<<"-----------------------------------------------------------\n"<<endl;cs = 0, ss = 0;createSrand(a,Size,i);cout<<"Level="<<i<<" quickSort:";quickSort(a,1,Size-1,cs,ss);cout<<"  cs="<<cs<<"  ss="<<ss<<endl;cout<<"-----------------------------------------------------------\n"<<endl;cs = 0, ss = 0;createSrand(a,Size,i);cout<<"Level="<<i<<" selectSort:";selectSort(a,Size,cs,ss);cout<<"  cs="<<cs<<"  ss="<<ss<<endl;cout<<"-----------------------------------------------------------\n"<<endl;cs = 0, ss = 0;createSrand(a,Size,i);cout<<"Level="<<i<<" heapSort:";heapSort(a,Size-1,cs,ss);cout<<"  cs="<<cs<<"  ss="<<ss<<endl;cout<<"-----------------------------------------------------------\n"<<endl;}
}
int main(){int a[Size];testLevel(a, Size);return 0;
}

上面有错, 还请指出, 如果认为我写的还不错, 还请点个赞, 多多支持一下, O(∩_∩)O~~

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

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

相关文章

我就随便BB一下

&#xff11;.如果我开始写文章的时候&#xff0c;停顿了几分钟&#xff0c;那结果应该很明显&#xff0c;这一定是一篇比较垃圾的文章&#xff0c;没什么东西值得看&#xff0c;所以我把之前的删除了&#xff0c;重新开头来写&#xff0c;我认为&#xff0c;一个好的开头一定是…

和我一起探索嵌入式

&#xff11;.本文为微信群管理员小磊投稿作品&#xff0c;作者计划编写一系列文章&#xff0c;该篇为第一篇&#xff0c;如果有做STM32的同学这将是一个非常好的系列教程&#xff0c;欢迎关注。我15年刚建立了一个BLE的QQ群&#xff0c;很有幸认识了小磊同学&#xff0c;一个非…

Java NIO_I/O基本概念_Java中的缓冲区(Buffer)_通道(Channel)_网络I/O

I/O基本概念 缓冲区基础 缓冲区是I/O的基础, 进程使用read(), write()将数据读出/写入从缓冲区中; 当缓冲区写满, 内核向磁盘发出指令, 将缓冲区中数据写入磁盘中(这一步不需要CPU), 当磁盘控制器将缓冲区装满, 内核将缓冲区数据拷贝到进程中指定的缓冲区; 操作如下图: 当中…

跟一个大佬前辈交流了一下

&#xff11;.最近&#xff0c;跟我们公司的测试总监聊天&#xff0c;我随便问了下他几个问题&#xff0c;他也给出了答案&#xff0c;在这里随便聊下&#xff0c;希望给大家的职业生涯中有一些借鉴的作用。也能给新入职场的同学一些方向和指引。2.先介绍下这个技术总监&#x…

LINQ简记(1):基本语法

关于LINQ&#xff08;语言集成查询&#xff09;是.NET 3.5和Visual Studio 2008以上版本中引入的一种有趣的全新概念&#xff0c;语言版本有VB和C#&#xff0c;由于C#与.NET平台结合最为紧密&#xff0c;也是MS当初首推的语言&#xff0c;因此&#xff0c;本系列文章的示例代码…

我认识的一位前辈~

&#xff11;.我最近认识了一个老前辈&#xff0c;关注了我的公众号加了我的好友认识的&#xff0c;我想介绍一下这位前辈&#xff0c;不是因为他有多成功&#xff0c;也不是因为他给了我很多钱&#xff0c;我觉得他是一个在平常不过的人了&#xff0c;因为太过于平凡的思考方式…

机器学习_决策树_ID3算法_C4.5算法_CART算法及各个算法Python实现

下面的有些叙述基于我个人理解, 可能与专业书籍描述不同, 但是最终都是表达同一个意思, 如果有不同意见的小伙伴, 请在评论区留言, 我不胜感激. 参考: 周志华-机器学习 https://blog.csdn.net/xiaohukun/article/details/78112917 https://blog.csdn.net/fuqiuai/article/d…

http数据绑定spring mvc详解

转载于:https://www.cnblogs.com/panxuejun/p/6834365.html

ESP32 入门教学,不入门,不教学

&#xff11;.Internet of things &#xff08;iot&#xff09;这个概念非常火&#xff0c;物联网是什么&#xff1f;把所有物品通过射频识别等信息传感设备与互联网连接起来&#xff0c;实现智能化识别和管理。 物联网通过智能感知、识别技术与普适计算、泛在网络的融合应用&a…

一个从华为离职的朋友

1、我在之前的很多文章里面都谈到了我有一个过硬的华为朋友&#xff0c;我很少去炫耀自己有多厉害&#xff0c;认识了谁谁&#xff0c;但是我非常在意那些跟自己有过交情的朋友&#xff0c;这些朋友不是说你离开了就失去了&#xff0c;也不是你落魄了就不能吹水了&#xff0c;今…

机器学习_简单线性回归与多元回归方程原理推导_处理二值数据_最小二乘法解或梯度下降解多元回归方程(详细推导)以及Python代码实现_回归方程度量方式

下面的有些叙述基于我个人理解, 可能与专业书籍描述不同, 但是最终都是表达同一个意思, 如果有不同意见的小伙伴, 请在评论区留言, 我不胜感激. 参考: 周志华-机器学习 最小二乘法求解多元回归方程: https://blog.csdn.net/weixin_39445556/article/details/83543945 梯度下…

手写Java线程池_超详细解说_绝对能运行_代码超详细注释

线程池 问题背景 只是单纯使用 new Thread(runnable).start(); 的方式创建线程, 将会导致严重的程序性能问题: 1.线程创建, 销毁需要消耗很大的系统资源; 2.虚拟机创建线程的数量是有限的; 2.线程调度切换也将使程序性能下降; 针对这些问题, 对线程数量进行管理, 有效地重复利…

分享一个非常 nice 的工具

最近有个问题&#xff0c;我需要经常使用远程连接工具&#xff0c;原因很简单&#xff0c;我需要控制另外一台电脑&#xff0c;我刚开始使用的是 teamviewer 这个软件&#xff0c;刚开始用的时间是非常爽的&#xff0c;不过有一天他给我来了个提示&#xff0c;说我的软件被商用…

推荐周立功先生的一本书

1. 这篇文章主要是推荐周工的一本书&#xff0c;大家在学习嵌入式的时候&#xff0c;很多人不明白嵌入式系统和单片机的区别&#xff0c;又感觉自己对嵌入式有所了解&#xff0c;知道什么是嵌入式&#xff0c;文章里的很多见解我觉得对很多人都非常有帮助&#xff0c;今晚上周工…

图管够!灌篮高手、女儿国…阿里日_这帮程序员太会玩了!

5月10日是阿里一年一度的阿里日&#xff0c;这对阿里人来说&#xff0c;是个非常特别的日子。 那什么是阿里日呢&#xff1f;看看官方介绍&#xff1a; 它起源于2005年4月20日&#xff0c;是为了纪念2003年5月的“非典”时期阿里人的激情和信念。因此阿里巴巴决定&#xff0c;今…

复习Collection_迭代器使用细节_泛型_综合案例

Collection_迭代器使用细节_泛型_综合案例 主要内容 Collection集合迭代器增强for泛型 第一章 Collection集合 1.1 集合概述 集合&#xff1a;集合是java中提供的一种容器&#xff0c;可以用来存储多个数据。 集合和数组既然都是容器&#xff0c;他们之间的区别: 数组的…

Kubernetes dashboard集成heapster

图形化展示度量指标的实现需要集成k8s的另外一个Addons组件&#xff1a; Heapster 。 Heapster原生支持K8s(v1.0.6及以后版本)和 CoreOS &#xff0c;并且支持多种存储后端&#xff0c;比如&#xff1a; InfluxDB 、 ElasticSearch 、 Kafka 。 下载源包和images文件 下载地址h…

ESP32 分区介绍

软件设计分区表 如上图是正常运行需要的分区&#xff0c;一个系统的正常运行是需要这么多分区的。 分区表&#xff0c;我们软件默认配置的分区表如下 # Espressif ESP32 Partition Table # Name, Type, SubType, Offset, Size, Flags nvs,data,nvs,0x9000,16K, otadata,data,…

python坦克大战_Life is short,you need Python——Python实现坦克大战(一)

先展示一下效果搓搓小手手&#xff0c;坦克大战即将开始……https://www.zhihu.com/video/1140743290784817152一、游戏引擎的安装安装方式有两种&#xff1a;1.pip安装 windows R --> cmd --> pip install pygame2.pycharm安装 File -->setting -->project -->…

复习Java字节流_字符流使用及案例

字节流_字符流 主要内容 IO流字节流字符流异常处理Properties 第一章 IO概述 1.1 什么是IO 生活中&#xff0c;你肯定经历过这样的场景。当你编辑一个文本文件&#xff0c;忘记了ctrls &#xff0c;可能文件就白白编辑了。当你电脑上插入一个U盘&#xff0c;可以把一个视频…