排序算法(三) —— 插入排序
来源:互联网 发布:超越无限 知乎 编辑:程序博客网 时间:2024/06/03 14:53
原创文章,转载请注明出处。
本文是排序算法系列文章的第三篇,主要讲述 “插入排序” 算法。
一、原理: 插入排序的基本操作是每步将一个待排序的对象,按其关键字大小,插入到前面已经排好序的数据序列的适当位置上,直到对象全部插入为止。当插入第 i(i >= 1)个对象时,前面的 a[0], a[1], …, a[i - 1] 已经排好序。用 a[i] 与 a[i - 1], a[i - 2], … 顺序进行比较,若 a[x] 大于 a[i],则从 a[x] 开始顺序后移,找到插入位置即将 a[i] (inserter)插入。
二、代码及注释:
void insertSort(int n, int *arr){int i, j;int inserter;// 插入点,也即待插入值for (i = 1; i < n; i++)// 只需排 n - 1 趟,因为第 i 趟时,前面的 i - 1 个数均已排好序{inserter = arr[i];// 待插入值for (j = i - 1; j >= 0 && inserter < arr[j]; j--)// 从待插入值的前一个位置开始,从后往前查找,找到大于待插入的数的位置{arr[j + 1] = arr[j];// 从该位置往后顺移,并接着查找直至已排序列的某个位置及之前的位置均不再有大于待插入值的数据}arr[j + 1] = inserter;// 这个位置之后的一个位置(因为跳出循环时j多减了 1 次)即为插入位置}三、算法性能分析:
当输入规模为 n = 10000、20000、30000、40000、50000 时,执行程序,可以得到在不同输入规模下,20 组随机样本数据执行插入排序的单组执行时间及平均执行时间为:
理论上来说,插入排序的时间复杂度为 O(n2)。同时,由上图可以看出,当 n = 10000 时,20 组样本排序的平均执行为 13.2813 ms。以输入规模为 10000 的数据运行时间为基准点,则理论上的平均执行时间为:t = k * n2,(k 为常数),代入 t = 13.2813 ms、n = 10000,可得:k = t / n2 =13.2813 / 100002 。
所以,在相应输入规模下,插入排序的理论执行时间为:
根据上表,可以作出插入排序理论效率曲线和实测效率曲线如下:
如上图表,是插入排序的理论效率曲线和实测效率曲线,位于上方的数据标签是实测效率曲线的标注,位于下方的数据标签是理论效率曲线的标注。由图表我们可以看出,在问题规模固定时,理论消耗时间和实际消耗时间十分相近,二者吻合得很好。
同样地,我们可以比较直观地看出,对于理论效率曲线和实测效率曲线,都大致满足抛物线 y = k * n2 在某个定义域的一段曲线(其中 k 为系数)。这与我们的理论认知也是相一致的。
在插入排序过程中,每步将一个待排序的对象,按其关键字大小,插入到前面已经排好序的有序表的适当位置上,直到对象全部插入为止。若初始序列为正序,则每趟只需与前面有序记录序列的最后一个记录比较 1 次,移动 2 次记录,总的关键字的比较次数为 (n - 1),记录移动次数为 2(n - 1);若初始序列为逆序,则第 i 趟时第 i 个记录必须与前面 i 个记录都做关键字比较,并且每做 1 次比较就要做 1 次数据移动,那么比较操作次数为 n(n - 1) / 2,记录移动操作次数为 (n + 4)(n - 1) / 2;若待排序记录是随机的,即待排序序列中的记录可能出现的各种排列的概率相同,则我们可以取上述最小值和最大值的平均值作为插入排序所需关键字比较和移动操作次数,约为 n2 / 4。因此,总的时间复杂度为 O(n2),这也是理论效率曲线所反映出来的。 而实测效率曲线与理论效率曲线吻合得很好,随着输入规模的增大,实际消耗时间与理论消耗时间基本相同。但也可以看到一点趋势,在输入规模越来越大时,移动操作也会像冒泡排序一样对最终时间消耗造成影响,但不至于像冒泡排序一样影响那么大。就实验结果来看,理论效率曲线与实测效率曲线的一点细微差异,可能是少量移动操作引起的。
- 排序算法三——插入排序
- 排序算法(三)——插入排序及改进
- 排序算法自我练习(三)——插入排序
- 排序算法(三)——插入排序
- 排序算法(三)——插入排序及改进
- 排序算法(三) —— 插入排序
- 排序算法(三)——插入排序及改进
- 排序算法——插入排序(直接插入排序、折半插入排序、希尔排序)
- 排序算法(三)之插入排序
- 排序算法总结(三)插入排序
- 排序算法(三)直接插入排序
- 排序算法(三)直接插入排序
- 排序算法(三)- 直接插入排序
- 排序算法(三)插入排序
- 排序—插入排序算法
- 排序算法—插入排序
- 基础排序算法(三)——对半插入排序
- 一句话明白排序算法之三——插入排序
- 链表的创建与输出
- 升级Win下工具链以支持C++17
- TextView、Button的drawableLeft和drawableRight与文本一起居中显示
- UITableView嵌套WKWebView的那些坑
- Promise-使用整理
- 排序算法(三) —— 插入排序
- 机器学习实战 笔记 debug kNN (三)
- 数据库索引类型及实现方式
- MongoDB 与 MySQL操作数据库对比
- 2017半年总结
- GIT的简易搭建(Window下)
- Object 用法
- es6环境中,export与import使用方法
- Join有关的几种连接查询