超级简单的插入排序
Posted 代码两三事
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超级简单的插入排序相关的知识,希望对你有一定的参考价值。
插入排序和冒泡、选择一样都算是一种超级简单的排序算法。插入排序名字里有个插入,它的排序算法确实和插入这个动作有关。基本思想是把数据分为两部分,一部分已经排好序,另外一部分待排序。然后将一个待排序的元素插入到已排序元素的合适位置。最终得到一个排好序的元素集合。
算法步骤
将第一个元素看为是已经排好序的集合,从二个元素开始到末尾认为是待排序集合;
从待排序集合的第一个位置拿出元素,标记为新元素;
从已排序元素集合的末尾开始往前扫描,如果元素大于新元素,则向后挪动一位;
重复步骤3,直到找到的已排序元素小于或者等于新元素的位置。在此位置插入新元素;
重复动作2到4;
尝试实现
图1
第一步,我们将整个数组分为已排序和待排序两部分。绿色为已排序,白色为待排序(图1)。并且准备好指针j,指向已排序集合的末尾元素。
第二步,从待排序集合中拿出第一个待排序元素,标记为新元素(图2)。
图2
第三步,开始比较temp和j指向的元素大小。此时temp元素6大于j元素4,遍历结束。j+1=1,即array[1] 位置为temp的合适位置。插入。结果如下:
图3
接着开始第二轮排序。此时j指向1号位,i标记未排序元素的首元素指向2号位,temp=array[i]。如图4所示。
图4
这时比较temp和j指向的元素大小,6大于1。已排序元素6向后挪动一位,完成后j指针向左挪动一位。
图5
再次比较temp和j指向的元素,4大于1,已排序元素4向后挪动一位,j指针向左挪动一位。
图6
此时j=-1,发生越界,循环结束。j+1=0,0号位即为temp的合适位置。插入,结果如下:
图7
至此我们发现只要重复前面的第二步和第三步即可完成剩下的排序工作。
以上步骤用代码实现一下:
public static void insertSort(int[] array) {
if (null == array || array.length < 2) return;
//默认第一个元素是已排序元素,所以i直接从1开始
for (int i = 1; i < array.length; i++) {
int temp = array[i];//在待排序集合中选择第一个元素为新元素
int j = i - 1; //找到已排序元素的末尾
//从已排序集合的末尾开始向前扫描,只要元素大于新元素,就向后挪动一位
while (j >= 0 && array[j] > temp) {
array[j+1] = array[j];//向后挪动一位
j--;//指向已排序元素的指针减减,向左挪动一位
}
//此时j+1的空位就是新元素在已排序集合中合适的位置。插入即可
array[j+1] = temp;
}
}
算法分析
时间复杂度
最好情况:从上面的操作步骤来看,插入排序的最好情况当然是数组是一个已经排好序的数组。选中的temp元素和已排序元素的末尾元素比较一次即可。总共比较N-1次,此时时间复杂度为
最坏情况:同理,当待排序数组为逆序时就是最坏情况,比较的次数也最多,为1+2+3+…+N-1。这时的时间复杂度为
平均时间复杂度:插入排序平均时间复杂度和最坏情况一样,均为
空间复杂度
由上面的算法尝试实现过程中发现我们使用到了一个temp存储元素,所以得出插入排序的空间复杂度是O(1)
算法稳定性
还是观察上面的算法尝试实现过程,对于值相同的元素,我们选择将后面出现的元素,插入到前面出现元素的后面(我们采用的条件是array[j] > temp),这样就可以保持原有的前后顺序不变。
因此得出结论插入排序是稳定的排序算法。
以上是关于超级简单的插入排序的主要内容,如果未能解决你的问题,请参考以下文章
c_cpp 这个简单的代码片段显示了如何使用有符号整数在C中完成插值。 for()循环确定要插入的范围
直接插入排序 ,折半插入排序 ,简单选择排序, 希尔排序 ,冒泡排序 ,快速排序 ,堆排序 ,归并排序的图示以及代码,十分清楚