【开发者笔记】插入排序改进

最近在书上看到一个习题说能把插入排序的复杂度通过改变插入规则为二分法从而降低时间复杂度到nlgn,我自己下来试了试发现想法倒是没问题,但实现起来有点小难点。

一般的插入排序时间复杂度为O(n2)毋庸置疑,但是用二分法插入同样需要移动大量数组元素,查找下标的时间复杂度降低到了O(nlgn),但是移动数组元素的时间复杂度依然是O(n2)……哪位大神赐教赐教~

插入排序时间复杂度分析:

public static void insertionSort(int[] arr) {          
        for (int j = 1; j < arr.length; j++) {          //c1*n
            int key = arr[j];                    //c2*n
            int i;                           //c3*n
            for (i = j - 1; i >= 0 && arr[i] > key; i--) {   //c4*n*(n+1)/2
                arr[i + 1] = arr[i];                //c5*n*(n+1)/2
                }
            arr[i + 1] = key;                    //c6*n
        }
    }

时间复杂度T(n)=(c4+c5)*n*(n+1)/2+(c1+c2+c3+c6)*n=O(n2);

改进后的插入排序:


/*插入排序的改进版,用二分法插入从而取代一次次的比较,减小了n*n-nlgn的时间复杂度*/
public static void inproveInsertionSort(int[] arr) { for (int j = 1; j < arr.length; j++) {      //c1*n int key = insertToArray(arr,0,j-1,j);    //c2*n*log2n int temp=arr[j];                //c3*n for(int i=j;i>key;i--){            //c4*n*(n+1)/2 arr[i]=arr[i-1];              //c5*n*(n+1)/2 } arr[key]=temp;                  //c6*n } } /*二分法查找key应该插入有序数组arr【b,e】的位置,返回应当插入的数组index,递归查询*/ public static int insertToArray(int[]arr,int b,int e,int key){  //nlog2n if(b>=e){ if(arr[key]<arr[b]){ return b; } else return b+1; } int mid=(b+e)/2; if(arr[key]<=arr[mid])return insertToArray(arr,b,mid,key); return insertToArray(arr,mid+1,e,key) ; }

如果用其他的数据结构【1】而不用数组省去移动数组操作的话,也就是省去c4c5部分。则时间复杂度为:

T(n)=c2*n*lgn+(c1+c3+c6)n=O(nlgn)----------------------------------------lgn=log2n

时间复杂度降低到比较排序的下Ω(nlgn),可以和合并排序媲美了~

 【1】:这里说的用其他数据结构就是比如链表,但是又出现一个新问题,用链表虽然去除了大量移动数组元素带来的时间占用,同时也带来了二分法查找数据的困难。目前我还没想到办法实现。引用第二版算法导论译本,上面也只有改进的习题但是没有答案~就先到这里吧。

引用:算法导论第二版

2016-11-01 

转载于:https://my.oschina.net/stagebo/blog/1620941

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值