插入排序(Insertion Sort)的过程就像我们排序扑克牌一样(从左到右,从小到大)。开始时我们左手为空,然后我们从桌子上拿起一张牌并将它插入到左手中正确的位置,为了找到这个位置,我们将这张牌与左手中从右向左的每张牌进行比较,直到找到比它小或相等的牌的后面。
与排序扑克牌类似插入排序的原理是:将数组中的数据分为两个区间,已排序区间和未排序区间。初始已排序区间只有一个元素,就是数组的第一个元素,接着取未排序区间中的元素(数组的第二个元素),在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序,重复这个过程,直到未排序区间中元素为空。
还是上篇文章中的需求:
排序前:4, 6, 3, 5, 2, 1
排序后:1, 2, 3, 4, 5, 6
算法过程:
1、从第一个元素开始,该元素可以认为已经排序;
2、取出下一个元素,在已排序区间中倒序遍历;
3、如果已排序元素大于新元素,将已排序元素移动到下一个位置;
4、继续向前遍历,重复上一步骤直到找到已排序的元素小于或等于新元素,将新元素插入已排序元素的后面;
5、重复2-4步骤。
为了便于大家理解,我画了张图
完整代码如下,仅供参考
public class InsertionSort {
public void sort(int[] arr) {
int len = arr.length;
if(len <= 1) {
return;
}
for(int i = 1; i < len; i++) { // 未排序区间
int item = arr[i]; // 待排序元素
int j = i-1;
for(;j >= 0; j--) { // 已排序区间
if(arr[j] <= item) {
break;
} else {
arr[j+1] = arr[j]; // 已排序区间元素后移
}
}
// 待排序元素的位置
arr[j+1] = item;
}
}
}
总结
1、插入排序的时间复杂度是多少?
如果要排序的数据已经是有序的,如果我们是在已排序区间倒序遍历查找,每次只需要比较一个数据就能确定插入的位置。所以在这种情况下,最好的时间复杂度为O(n)(注意,这里是倒序遍历)。
如果要排序的数据刚好是相反的,每次插入都相当于在数组的第一个位置插入新的数据,需要移动大量的数据,所以最坏的时间复杂度为O(n^2)。
2、插入排序的空间复杂度是多少?
从上述实现过程可以看出,插入排序没有额外的存储空间,所以它的空间复杂度为O(1)。这是一个原地排序算法。
3、插入排序是稳定的排序算法吗?
在插入排序中,对于值相同的元素,我们可以将新元素插入到已排序区间元素的后面,这样就可以保持原有的顺序不变,所以插入排序是稳定的排序算法。
「更多精彩内容请关注公众号geekymv,喜欢请分享给更多的朋友哦」