首页 > 编程语言 >排序算法以及TOP 10(算法实验一)

排序算法以及TOP 10(算法实验一)

时间:2024-03-15 20:58:43浏览次数:26  
标签:10 TOP 算法 时间 ms 排序 数据 运行

  • 实验目的
  1. 掌握选择排序、冒泡排序、合并排序、快速排序、插入排序算法原理
  2. 掌握不同排序算法时间效率的经验分析方法,验证理论分析与经验分析的一致性。

  • 问题重述(问题描述):

问题一:

实现选择排序、冒泡排序、合并排序、快速排序、插入排序算法

问题二:

生成20组数量规模为n(10万,20万,30万,40万,50万)的待排序随机数,然后用上述五种排序算法计算这20个样本的平均运行时间。并且要做出这五个排序算法在20个随机样本的平均运行时间,理论运行时间与输入规模n的关系曲线图(横纵坐标都要均匀)。比较两条曲线,理论和实际是否一致,不一致要分析给出原因。

问题三:

有10亿的数据(每个数据四个字节),请快速挑选出最大的十个数,并在小规模数据上验证算法的正确性。

  • 实验原理(代码思想以及求解问题的算法原理描述):
  1. 选择排序:

第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素。(一般都是挑最小的数)

Fig1:选择排序原理图

      2.冒泡排序:

相邻的两个元素进行比较,按照要求进行交换。

Fig2:冒泡排序原理图

3.合并排序:

先将数组中的元素拆分成若干小部分,然后再将这些小部分按照顺序进行重新组合,从而实现排序。(有点分治法的味道)

4.快速排序:

     将比这个数大或等于的数全放到它的右边,小于它的数全放到它的左边(为由小到大排序)

5.插入排序:

将一个数插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。

6.TOP 10:

按照正常思路肯定是便利数据10遍选择最大的十个数(即为选择排序)

可以选取上述五种排序算法中的最高效的来排序。

堆排序,维护10个数的小顶堆。

理论分析:

每个数据是4字节,那么10亿个数据就是40亿byte=3.725 G;所以在测试TOP 10时要预留足够的储存空间来存放待排的样本。

三、实验内容:

排序问题要求我们按照升序排列给定列表中的数据项,目前为止,已有多种排序算法提出。本实验要求掌握选择排序、冒泡排序、合并排序、快速排序、插入排序算法原理,并进行代码实现。通过对大量样本的测试结果,统计不同排序算法的时间效率与输入规模的关系,通过经验分析方法,展示不同排序算法的时间复杂度,并与理论分析的基本运算次数做比较,验证理论分析结论的正确性。

流程图

  • 实验过程及其优化分析(算法实现的核心伪代码以及算法测试结果及效率分析):

设计随机数生成20组样本:

先是设置生成随机数样本,一开始使用的是rand()这个函数;但发现每次产生的随机数虽然随机,但每个生成的随机数样本是一模一样的,缺乏说服力。然后我就是又去查了一下其他的生成随机数的方法mt19937随机数方法。

Fig:生成随机数的伪代码

通过小规模的数据生成发现:mt19937 随机数引擎生成的数比较随机,且数的范围比较大,数据比较杂乱,会使得我们后续的排序实验更加具有说服力。

接着为了更加方便我们跑数据我直接让程序一次性跑完20个样本并且把算出的数据给跳出来,解放劳动力。

Fig:一起运行20个样本的伪代码

  1. 选择排序(O(n2)):

1.1简单选择排序:

第一次从待排序的数据元素中选出最小的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素。

Fig3:选择排序伪代码

实际:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

5657

23451

54387

98447

154215

理论:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

5657

22784

51264

91136

142400

Fig4:选择排序实际与理论时间的曲线

分析:实际和理论运行时间曲线大致吻合,后面数据规模变大时出现了小偏差,可能测试的数据还不够多,导致平均实际运行时间纯在偶然性,有点小偏差。

可优化的方向:

  1. 因为一趟下来只排好了一个数,所以可以设计趟下来同时排好最大和最小的(一趟下来排好两个数)。

1.2优化的选择排序

Fig5:优化的选择排序伪代码

实际:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

4238.75

17032

37788.67

66642.67

106555.7

理论:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

4238.75

16955

38148.75

67820

105968.75

Fig6:优化的选择排序实际与理论时间的曲线

分析:理论和实际运行时间曲线大致吻合,拟合度高。

简单与优化对比:

效率有着明显的提升。优化后的选择排序虽然操作数增加了,但仍比简单的选择排序要高效。

2.冒泡排序:

2.1简单冒泡排序:

Fig7:冒泡排序伪代码

实际:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

35367

137851

305605

545475

859000

理论:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

35367

141468

318303

565872

884175

Fig8:冒泡排序实际与理论时间的曲线

分析:理论和实际运行时间曲线大致吻合,拟合度高。由于每趟排序进行了很多次交换,使得操作变得复杂,所以运行时间也比选择排序要大的多。

 

可以优化的方向:

  1. 可以设置一个变量flag,来判断该趟冒泡是否有发生交换,如果flag的状态发生改变,说明该趟冒泡有发生交换,如果没有交换,说明这一趟排序前一个位置的数都比后一个位置的数小或者等于,即已经排好序,可以提前结束排序
  2. 可以设置一个变量last,来记录最后一次交换的位置,然后下次遍历只用遍历到last即可,因为last后面的数已经排好序了。

2.2优化的冒泡排序:

Fig9:优化的冒泡排序伪代码

实际:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

23887

96103

216001

383713

600446

理论:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

23887

95548

214983

382192

597175

Fig10:优化的冒泡排序实际与理论时间的曲线

分析:理论和实际运行时间曲线大致吻合,拟合度高。

简单与优化对比:

效率有着极大的提升。

 3.合并排序

Fig11:合并排序伪代码                                

实际:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

24.33

51.85714

85

120.5

153.4286

理论:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

24.33

51.5896

79.96

109.038

138.6556

Fig12:归并排序实际与理论时间的曲线

分析:对于快排来说,此数据规模偏小,所以造成了实际和理论的运行时间有着较大的偏差,但总体来说实际与理论大致吻合。

 

4.快速排序

Fig13:快速排序伪代码                                

实际:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

7.5

18.45

28.85294

45

61.69231

理论:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

7.5

15.903

24.647

33.61236

42.74228

Fig14:快速排序实际与理论时间的曲线

分析:对于快排来说,此数据规模偏小,而且递归函数的调用也耗了很多时间。所以造成了实际和理论的运行时间有着较大的偏差,但总体来说实际与理论大致吻合。

5.插入排序

Fig15:插入排序伪代码                                

实际:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

7337.5

29683.5

67651.5

119289.5

186942.5

理论:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

7337.5

29350

66037.5

117400

183437.5

Fig16:插入排序实际与理论时间的曲线

分析:实际与理论的运行时间曲线大致吻合,重合度高。

可以优化的方向:

  1. 在插入过程中因为插入的数是已经有序的,所以可以使用折半查找来找到要插入的位置。

理论:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

4012

17868

43740

81779

127270

实际:

数据规模n

100000

200000

300000

400000

500000

运行时间/ms

4012

16046

36108

64192

100300

6.TOP 10

有三种可行的算法:

  1. 第一种就是选择排序,便利10次选出最大的十个数    O(n*10)
  2. 第二种就是通过上面对比课得知快速排序是最快的,可以先排序好再选10个最大的数O(nlog(n))
  3. 第三种就是堆排序,维护十个数的小顶堆。O(nlog(k))

当选10个最大数时:

数据规模

选择排序

快速排序

堆排序

1千万

1689ms

17126ms

150ms

2千万

3752ms

33057ms

340ms

当选100个最大数时:

数据规模

选择排序

快速排序

堆排序

1千万

16597ms

17157ms

178ms

2千万

34285ms

33175ms

469ms

分析:当数据规模越多时选择和堆排序增长的速率近乎成比例翻倍,但当选出最大数的规模增大时,快排的变化不明显,选择和对排序仍是成比例翻倍。所以当选的数少时可以考虑使用选择和堆排序。选择最大数的数量大时可以考虑快排和堆排序,但总体而言,堆排序在TOP K这类问题中都明显优于选择排序和快速排序,这说明堆排序算法在这个问题中的正确性。

现在有10亿的数据(每个数据四个字节),请快速挑选出最大的十个数

使用堆排序可以在20000ms左右搞定。

Ps:每个数据是4字节,那么10亿个数据就是40亿byte=3.725 G;所以在测试TOP 10时要预留足够的储存空间来存放待排的样本(本次实验发现最少要给c盘留够12G的空间)。

 

五、讨论与总结(请阐述实验过程中所遇到的问题及解决办法,或者后续可以继续探索的问题等)

1.对算法的优化不能纸上谈兵。

在原有基础代码中其实有很多冗余的操作,比如排好序的任要继续遍历等,所以要多敲多实践,当然也不能只是想当然,比如选择排序空以为一趟下来排好两个位置会使运行时间减半,但其实也增加了一趟下来的操作,虽有优化,但也不至于是减半。

2.算法的运行时间在不同时刻会有所不同。

可能冒泡排序在今天我测的时候的运行时间会是我明天运行时间的不太一样,可能是对计算机的运行较多导致精度有点偏差,所以要测量某个算法最好是当天跑完所以数据。

3.不同的数量级要使用不同的算法来进行排序。

当数据规模一大的时候,快排和归并排序的优势就会凸显,所以当要排序的数据规模很大的时候,我们可以尽量选择快排与归并。

4.快速排序优于其他四个排序算法。

Fig17:五种算法对比

总的来说,快排是五种算法中最快的,但遇到极端情况数本来就有序就会降到O(n2)

但是由于随机生成随机数所以这种极端情况的出现概率为1n! 当数据规模比较大时可以基本忽略不看。冒泡排序虽然和选择排序以及插入排序的时间复杂度都为O(n2),但由于冒泡进行了更多的交换操作,所以平均运行时间也比选择排序以及插入排序要多

平均运行时间:冒泡排序>插入排序序>选择排序序>归并排序序>快速排序

5.当一些排序的运行时间比较久时可以想办法去优化。

比如去知网查文献

询问chatgpt等 

标签:10,TOP,算法,时间,ms,排序,数据,运行
From: https://blog.csdn.net/m0_63790127/article/details/136396111

相关文章

  • MD5算法:密码学中的传奇
    title:MD5算法:密码学中的传奇date:2024/3/1520:08:07updated:2024/3/1520:08:07tags:MD5起源算法原理安全分析优缺点比较技术改进示例代码应用趋势MD5算法起源:MD5(MessageDigestAlgorithm5)算法是由MIT的计算机科学家RonaldRivest于1991年设计的一种消息摘......
  • PBKDF2算法:保障密码安全的利器
    title:PBKDF2算法:保障密码安全的利器date:2024/3/1416:40:05updated:2024/3/1416:40:05tags:PBKDF2算法密码安全性迭代盐值密钥PBKDF2算法起源:PBKDF2(Password-BasedKeyDerivationFunction2)算法是一种基于密码的密钥派生函数,最初由RSA实验室的密码学家提出......
  • MD5算法:密码学中的传奇
    MD5算法起源:MD5(MessageDigestAlgorithm5)算法是由MIT的计算机科学家RonaldRivest于1991年设计的一种消息摘要算法。MD5算法最初被用于提供数据完整性和一致性的验证,后来被广泛应用于密码存储和数字签名等领域。MD5在线加密|一个覆盖广泛主题工具的高效在线平台(amd794......
  • snowflake算法时钟回拨问题: 基于逻辑时钟解决方案
    snowflake算法时钟回拨问题:基于逻辑时钟解决方案问题时间的生成完全依赖于本地时钟,在开启NTP协议的情况下,可能出现时钟回拨现象,此时服务不可用为了防止ID被顺序破解,通常自增值不会递增1,可以更加随机的添加递增值解决方案我们需要知道,时钟回拨问题是一个对......
  • snowflake算法时钟回拨问题: 基于逻辑时钟解决方案
    snowflake算法时钟回拨问题:基于逻辑时钟解决方案问题时间的生成完全依赖于本地时钟,在开启NTP协议的情况下,可能出现时钟回拨现象,此时服务不可用为了防止ID被顺序破解,通常自增值不会递增1,可以更加随机的添加递增值解决方案我们需要知道,时钟回拨问题是一个对......
  • snowflake算法时钟回拨问题: 基于逻辑时钟解决方案
    snowflake算法时钟回拨问题:基于逻辑时钟解决方案问题时间的生成完全依赖于本地时钟,在开启NTP协议的情况下,可能出现时钟回拨现象,此时服务不可用为了防止ID被顺序破解,通常自增值不会递增1,可以更加随机的添加递增值解决方案我们需要知道,时钟回拨问题是一个对......
  • 计算机毕业设计项目基于大数据和ALS算法实现的房源智能推荐系统
    概要  目前,现有的房源信息不够透明化大多中介混淆市场,内含不为人知的商业链。有经验的租客们会通过周边房价走势和走访周边房源对比调研、筛选适合自己的房源。同时,对于用户工作地点需求和各种人群类型如大学生群体,年轻小资,或者中年人,他们希望居住的环境要求各不相同各......
  • 基于深度学习算法的垃圾分类图像识别研究
    概要  在科技发达、智能时代中,深度学习、机器学习以及人工智能成为了高频词。它们看似深不可测,但是又离不开我们的生活。深度学习和机器学习是一种技术、而人工智能一种是一种体现。使用深度学习和机器技术,使机器拥有人的某种大脑结构从而来实现人的某种行为,它不仅解决了......
  • chapter10-非线性数据结构
    机试中考查的一些非线性数据结构,包括二叉树、二叉排序树、优先队列和散列表。1.二叉树(BinaryTree)对于二叉树来说,机试中常考的是其各种遍历方法,分为前序、中序、后序遍历,以及层次遍历。1.2二叉树遍历题目描述+输入输出题目描述:二叉树的前序、中序、后序遍历的定义。前......
  • 面试被问道:LRU算法的优化手段(二)
    大家好,我是程序员阿药。接上一篇LRU算法的优化手段(一),今天分享的是优化手段(二),也就是如何优化LRU算法解决缓存污染问题。话不多说,发车!当一次读取批量数据页时,这些数据页都将加入到activeList链表头部或hot区的链表头部,很有可能就会将之前的热点数据页从activeList或hot区中淘汰......