常见排序算法-插入排序
Posted 咸鱼成长小站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常见排序算法-插入排序相关的知识,希望对你有一定的参考价值。
上一节我们介绍了排序算法之选择排序,这一次我们来介绍一下排序算法中的另一个————直接插入排序
在介绍插入排序之前,先问大家一个问题,大家都玩过斗地主吧?
那么,在斗地主的时候你是怎么理牌的呢?我们知道,斗地主的牌除去大小王有13种牌面。它们的大小按从小到大排列为
3为最小,2为最大。我们在抽到一张牌的时候,我们会依据它的牌面大小,将它插入到合适的位置
比如说,我手牌里有3,5,6,9。那么假设我下一张抽到了4,我自然会将4插入到它合适的位置即3和5之间。
这就是一种插入排序。
插入排序就是将一个元素插入到另一个有序序列使新的序列依旧有序的算法。
插入排序是怎样来实现的呢,我们这儿介绍一下直接插入排序算法,其它还有二分插入排序,希尔插入排序等就不介绍了。
直接插入排序很好理解,当我需要插入一个新值时,我就简单的遍历一下整个数组,将有序序列中比它大的数都向后挪一位。这样我们就能找到这个数应该插入的位置,接着就将该位置的数赋值为我们待插入的值即可。
举个例子
假设我们有一个待排序序列:[8,7,6,9,5,4,2,1,3]
首先我们将第一个元素8看作为有序序列,因为单独一个数必然是有序的。后面剩余的元素全都是待插入的值。
第一趟排序
我们比较第2位和第1位的值。发现7 < 8,则我们需要将大于7的数都向后挪一位。我们首先用一个临时变量储存值7。然后将所有大于7的数后挪,最后把7插入到所有大于它的数之前即可。
排序结束后序列变为
[7,8,6,9,5,4,2,1,3]
这样,有序序列就变成了前两位,后面的为待插入的值。
第二趟排序
这一次我们需要比较第3位和第2位。发现6 < 8,同样,我们需要将大于6的所有数都向后挪一位,然后将6插入到所有大于6的数之前。
排序结束后序列就变成了
[6,7,8,9,5,4,2,1,3]
第三趟排序
这一次比较第4位和第3位,发现 9 > 8。则不用挪位置,直接将9插入在最后就可以。
之后的排序过程与上述类似,就是判断第i位和第i-1位的大小,如果第i位小于第i-1位,就需要将有序序列中所有大于第i位的数都向后挪一位,然后将第i位插入到这些数的前面。
过程讲完了,接下来我们来探讨一下直接插入排序它的时间复杂度。
对于一个已经有序的序列,插入排序代表着我们不需要进行挪位的过程,我们每一趟排序就只需要进行一次比较就结束了,所以共进行了n-1次比较。这样,我们的时间复杂度就为O(n)。即最优时间复杂度位O(n)。
对于一个倒序的序列来说呢,每一趟排序,我们都需要将有序序列中的所有数都向后挪一位。所以需要移动的次数为1+2+3+…+n-1。这种情况下我们的时间复杂读就为O(n^2),即最差时间复杂度O(n^2)。
直接插入排序代码样例
1#include <iostream>
2
3template <typename T>
4void insertSort(T *arr,int n){
5 if(n < 1)
6 return;
7 for(int i = 1;i < n;i++){
8 if(arr[i] < arr[i-1]){
9 T temp = arr[i]; //临时变量储存第i位的值
10 int j;
11 for(j = i-1;j >=0 && arr[j] > temp;j--){ //将所有大于第i位的元素都向后挪一位
12 arr[j+1] = arr[j];
13 }
14 arr[j+1] = temp; //将第i位的值插入到有序序列中
15 }
16 }
17}
18int main(){
19 int arr[9] = {8,7,6,9,5,4,2,1,3};
20 int len = sizeof(arr)/sizeof(arr[0]);
21 insertSort(arr,len);
22 for(int i = 0;i < len;i++){
23 std::cout<<arr[i]<<" ";
24 }
25 std::cout<<std::endl;
26 return 0;
27}
以上是关于常见排序算法-插入排序的主要内容,如果未能解决你的问题,请参考以下文章
常见排序算法基本原理及实现(快排,归并,堆排,直接插入.....)