10种排序算法比较(直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序、基数排序、折半插入排序、2路插入排序)

本文通过随机数据比较了直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序、基数排序的性能。在不同数据条件下,如乱序、正序、逆序,分析了各种排序方法的比较次数、移动次数和运行时间。实验结果显示,快速排序平均性能最佳,但具体情况需根据数据特点选择合适算法。例如,归并排序在大数据量时优于堆排序,基本有序数据可选冒泡排序或简单选择排序。

本文(所有排序算法代码+综合比较代码)链接:https://download.csdn.net/download/qq_39932172/11217572


一、比较目的:

       由于《数据结构》课本中各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶,或大概执行时间。所以我希望通过随机数据去比较各种算法的关键字比较次数和关键字移动次数,同时给出实际排序时间,以取得直观的感受。

二、比较内容:

  1. 对以下八种常用内部排序算法进行比较:直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序、基数排序。
  2. 待排序表的表长不小于 10 万;其中的数据用伪随机数程序产生;用5 组不同的输入数据做比较;比较的指标为有关键字参加的比较次数、关键字的移动次数(关键字交换记为 3 次移动)、排序时间。
  3. 最后对结果做简单分析,包括对各组数据得出结果波动大小的解释。

三、思想及具体体现:

总体思路:先点后面——就是先编好每一种算法,当每一种算法都能够运行的时候,然后再将所有的算法结合到一起,组合成综合设计。

具体体现

  1. 首先,用当前时间作为种子,用随机数生成器生成10000个随机数据,作为实验数据。
  2. 然后,用直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序、基数排序八种内部排序方法对实验数据进行排序,并记录各算法的关键字比较次数和关键字移动次数,以及实际排序时间。
  3. 最后,重复上述操作5次,总结上述数据,并进行比较分析。

四、实验结果分析和比较:

       为了更全面地比较各种比较方法的比较次数,移动次数和运行时间,我先后选取了全部都是乱序的数据,已排好的正序数据,已排好的逆序数据,前50000个乱序后50000个有序的数据,以及前50000个有序后50000个乱序的数据来分别进行比较,相关比较结果将在下面的实验结果中呈现。

1.乱序数据——每种比较方法均用了5组不同的乱序数据
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.正序数据——全部排序方法比较
在这里插入图片描述

3.逆序数据——全部排序方法比较
在这里插入图片描述

4.前50000乱序后50000有序——全部排序方法比较
在这里插入图片描述

5.前50000有序后50000乱序——全部排序方法比较
在这里插入图片描述

根据数据做出分析统计图如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

       通过对各种排序方法的比较之后,我们可以分析得出的是,不能够说哪种算法是好的,不同的算法都有好坏,我们只有根据不同的待排序数据,在不同的情况下去选择合适的算法。

       从平均时间性能而言,快速排序是最好的,因为其所用的时间是最少的。但是如果想到最坏的情况,当然就要考虑到堆排序和归并排序。堆排序对数据较多时是比较有效的,因为堆排序主要的耗时是在建初始堆和调整建新堆时进行的反复的“筛选”。当数据量很大时,归并排序所需时间较堆排序要少,但是归并排序所需要的辅助空间其实也要较多。如果所要排序的数据已经是基本有序的,为了节省时间和空间,可以选择冒泡排序和简单选择排序。

       从方法的稳定性来说,基数排序是稳定的内部排序算法,所有时间复杂度为O(n*2)的简单排序法也是稳定的,但是,快速排序、堆排序和希尔排序等时间较好的排序方法都是不稳定的。一般来说,排序过程中的“比较”是在“相邻两个关键字”间进行的排序方法是稳定的。

       因此,在所有的算法当中,没有哪一种算法是绝对最优的。有的适用于数据较多时,有的适合用于已经基本有序的数据,所以,在使用时需要根据不同的情况适当选用,甚至可将多种方法结合起来使用。


五、遇到的问题及解决的办法:

  1. 在分别进行每一种排序算法时,发现刚开始的设计出现了一点问题,比如当调用一种排序算法时,会将原有混乱的数据排序,在下一个排序算法要开始排序时该数据其实已经基本有序,所以影响了最终实验结果。所以后来修改为每次调用一个算法时都临时生成一个新的随机序列把之前的覆盖,即使这样操作造成时间上的浪费,但是也相比事先构造5个数组带来的内存浪费以及运行出现的错误要好一些,所以这样做还是比较可取的。

  2. 在用伪随机序列发生器来产生随机数的时候,由于srand()用当前的时间作为种子,而且如果用time()函数来获取当前时间的值的话,因为它是以秒(s)为单位,所以用做种子时会因排序时间过短而造成前后两次生成随机数组相同的情况。
    采取的解决办法是:用clock()函数代替time()函数来实现获取时间的功能,因为clock()函数是以毫秒(ms)为单位来获取时间的,代替之后即可解决种子相同的问题。

  3. 由于实验时待排序数据量过大,固定选取最低位的值作为枢纽的时候,容易导致快速排序时出现栈溢出的问题。
    采取的解决办法是:选取最低位,中间位,最高位三者之中数值在中间的那一个值作为枢纽,这样可以缓解栈溢出的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lil Wing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值