排序算法(1)--- 插入排序
大家好,我们又见面了,今天我来给大家介绍的是插入排序算法,直接插入法排序和希尔排序。
创作不易,别忘了一键三连!!!!!!!!!!!!
废话不多说,我们直接开启今天的内容。
一:排序的概念和应用
1. 概念:
排序:所谓排序,顾名思义就是使一串记录,按照其中的某个或者某些关键字的大小,递增或者递减排列起来的操作。
2. 运用:
排序在我们日常生活中应用很广,比如:
购物筛选排序:
院校排名:
3. 常见的排序算法:
比较常见的排序算法如下:
今天这一期,我们重点来了解第一类排序算法 --- 插入排序
二:直接插入排序
1. 算法原理:
直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键字码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。
文字是晦涩的,接下来通过一个案例来带领大家深刻的体会一下插入排序的流程:
我们将数组分成两个部分:1. 排好序的部分,2. 待排序的部分
我们发现,直接插入排序算法就是将待排序部分的元素一个一个的插入已经排好序的有序数组中。
这样的一个过程跟我们平常玩扑克牌摸牌的过程是大差不差的,实际中我们玩扑克牌时,就使用了插入排序的思想:
接下来通过一张动图来深刻理解一下这个插入的过程:
2. 代码实现
上述过程的代码实现相对来说也比较简单,就是简单的在有序区间中找到应该插入到的位置,然后挪动数据,把这个位置让出来即可。
我们定义两个变量:
1. end 标识有序序列的最后一个位置。
2. tmp 为待排序序列的第一个位置(接下来要插入的数据)。
接下来,就是插入数据的过程了,由于排好序的部分已经有序了。接下来就是比较 tmp 和 arr[end]
如果 tmp >= arr[end] 或者 end 已经走到 0 位置了,tmp 直接放在 arr[end + 1] 位置即可。
如果 tmp < arr[end],挪动数据 arr[end + 1] = arr[end],end--,继续比较。
// 直接插入排序
void InsertSort(int* arr, int n)
{for (int i = 0; i < n - 1; i++){int end = i;int tmp = arr[end + 1];while (end >= 0){if (arr[end] > tmp){arr[end + 1] = arr[end];end--;}else{break;}}arr[end + 1] = tmp;}
}
3. 分析时间复杂度
分析时间复杂度,首先要考虑最差的情况:
最差的情况下,从前向后遍历数组,每一个元素插入时,比较的次数依次为 1,2,3,…… n-1时间复杂度为 O(n ^ 2)(等差数列求和)。
最好的情况就是数组本来就是排好序的,这样的话,每一个元素插入时只需要进行一次比较就可以了。时间复杂度为 O(n)。
整体的时间复杂度还是要考虑最差的情况:O(n ^ 2)。
4. 总结
直接插入排序的特性总结:
1. 元素集合越接近有序,直接插入排序算法的时间效率越高
2. 时间复杂度:O(n ^ 2)
3. 空间复杂度:O(1)
三:希尔排序
1. 算法原理
希尔排序本质上是对直接插入排序算法的一种优化,我们知道,直接插入排序算法如果小的数据分布在前,大的数据分布在后的话,效率还是很不错的。希尔排序就是先通过预排序达成这样的一个状态,最后再进行一趟直接插入法排序。综合来所它的效率肯定是要高于直接插入排序算法的。
希尔排序法又称为缩小增量法。希尔排序法的基本思想是:先选定一个整数(通常是 gap = n/3+1),把待排序文件的所有记录分成各组,所有的距离相等的记录分在同一组内,并对每一组内的记录进行排序,然后 gap = gap / 3 + 1 得到下一个整数,再将数组分为各组,进行插入排序,当 gap = 1 时,就相当于直接插入排序。
2. 代码实现
在直接插入排序的外面套一层循环控制 gap 即可,另外注意边界问题和细节问题。
一组一组的直接插入法排序:
// 希尔排序
void ShellSort(int* arr, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;for (int i = 0; i < n - gap; i++){int end = i;int tmp = arr[end + gap];while (end >= 0){if (arr[end] > tmp){arr[end + gap] = arr[end];end -= gap;}else{break;}}arr[end + gap] = tmp;}}
}
3. 分析时间复杂度
4. 总结
希尔排序的特性总结:
希尔排序是对直接插入法排序的优化。
当 gap > 1 时都是预排序,目的是让数组更接近于有序。当 gap == 1 时,数组已经接近有序了,这样直接来一次直接插入法排序就会很快。这样整体而言,可以达到优化的效果。
好的,今天这一期就到这里了,我们下一期再见。