深入理解插入排序

在玩纸牌游戏的时候,为了使手中牌变得有顺序,我们常常需要把随机抽取到的纸牌插入到合适的位置。

在计算机中为了要给插入的元素腾出空间,需要将其后的元素在插入之前都右移一位,这种算法叫做插入排序

插入排序所需要的时间取决于输入中元素的初始顺序。假如,对一个很大且其中元素已经有序(或接近有序)的数组进行排序将会比随机顺序的数组或者逆序的数组排序要快的多。

结论一:

对于随机排列长度为N的且主键不重复的数组,平均情况下插入排序需要~(N^2)/4次比较以及~(N^2)/4次交换。最坏情况下需要~(N^2)/2次比较和~(N^2)/2次交换,最好情况下需要N-1次比较和0次交换。

public class Insertion {
	public static void sort(Comparable[] a) {
		/*具体算法的实现*/
		//将a[]按升序排列 		int N = a.length;
		for(int i = 1; i < N; i++) {
			//将a[i]插入到a[i-1]、a[i-2]、a[i-3]...之中 			for(int j = i ; j > 0 && less(a[j], a[j-1]); j--)
				exch(a, j, j-1);
		}
	}
        //可以自行实现其他功能,例如each等 }

《深入理解插入排序》
快速排序示意

我们要考虑的更一般的情况是部分有序的数组,倒置指的是数组中的两个顺序颠倒的元素。

比如E X A M P L E中有11对倒置:E-A,X-A, X-M, X-P, X-L, X-E, M-L, M-E, P-L, P-E 以及L-E。

如果数组中倒置的数量小于数组大小的某个倍数,那么我们说这个数组是部分有序的

下面是几种经典的部分有序的数组:

a、 数组中每个元素距离它的最终位置都不远

b、 一个有序的大数组接一个小数组

c、 数组中只有几个元素的位置不确定。

结论二:

插入排序需要的交换操作和数组中倒置的数量相同,需要的比较次数大于等于倒置的数量,小于等于倒置的数量加上数组的大小再减一。

要大幅提高插入排序的速度并不难,只要在内循环中将较大的元素都向右移动而不总是交换两个元素(这样访问数组的次数就能减半)

总的来说插入排序对于部分有序的数组十分高效,也很适合小规模数组。

    原文作者:SeYuFac
    原文地址: https://zhuanlan.zhihu.com/p/61348517
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞