插入排序
直接插入排序是一种简单的插入排序法。
- 基本思想:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
- 一段有序区间,插入一个数值仍然是有序区间。
- 先单趟再多趟,先局部再整体
实际中我们玩扑克牌时,就用了插入排序的思想
InsertSort直接插入排序
当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与 array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移。(记得先将array[i]的数值保存)
- n个数的下标为[0,n-1]
- end是下标❗❗❗
- 下标[0,end]是有序区间,end+1的下标插入这段有序区间仍是有序的。
- end的区间是[0,n-2](<n-1)
- end == 0 时候end+1 == 1下标为1的数据往下标为[0,0]这个有序区间插入
- end == n-2 时候end+1 == n-1下标为n-1的数据往下标为[0,n-2]这个有序区间插入
直接插入排序的特性总结:
1. 元素集合越接近有序,直接插入排序算法的时间效率越高
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1),它是一种稳定的排序算法
4. 稳定性:稳定
整体思路
- 一段有序区间,插入一个数值仍然是有序区间。
- end是下标❗❗❗
- 下标为end+1的数值,往下标为[0,end]的区间有序数值里插入,任然是有序数组
- n个数的下标为[0,n-1]
- end的区间是[0,n-2](<n-1)
- end == 0 时候end+1 == 1下标为1的数据往下标为[0,0]这个有序区间插入
- end == n-2 时候end+1 == n-1下标为n-1的数据往下标为[0,n-2]这个有序区间插入
- 整体思路:
- 每个数值插入
- 保存数值在tmp (下标为end+1)
- end+1与end比较。
- 若比end大则不交换;若比end小则end往后挪动,直到与end相等或者比end大结束循环。end+1=end(end--)(用tmp和end比较)
- 结束循环:情况1:tmp >=end ;情况2:end+1>=0(end>=0)
- 放入tmp到区间空缺的位置。下标为end+1的位置
- 一趟:每个数值插入
- 整体:n个数值插入
- 数据结构通用所有类型。
图解分析
代码实现
//升序 void InsertSort(int* a, int n) { //[0,end]end+1插入 for (int i = 0; i < n - 1; i++) { int end=i; int tmp = a[end + 1]; while (end >= 0) { if (a[end] > tmp) { a[end + 1] = a[end]; end--; } else//<= { break; } } a[end + 1] = tmp; } }
时间复杂度
时间复杂度: O(N^2)
- 最坏的情况逆序:O(N^2)
- 最好的情况顺序&接近顺序:O(N)
- 直接插入和冒泡排序都是等差数列,直接插入近似等差数列。
- 直接插入排序和冒泡排序的时间复杂度是一个等级的。
- 但是直接插入排序效率更好。(月薪10万和月薪1万的差距)
- 关于直接插入排序的稳定性和性能比较最后会归纳总结
🙂感谢大家的阅读,若有错误和不足,欢迎指正。