算法导论2.3-6参考

    按照题目描述,我们需要将插入排序中的5~7行,while循环实现的将“比A[i]大的数后移”的功能用二分查找的思路进行优化。2.3-5也有提到优化思路,即插入排序每一次循环结束后前面的i个数已经完成从小到大的排序,只需要将目标值A[j]与前i个数的中间值A[i/2]比较,就能知道A[j]应该在的区间,并减少一半的判断时间。

    伪代码://_(:зゝ∠)_

BINARY_INSERTION_SORT ( A , L , R )//输入A[0..n],0,n

    if R > 2……………………………………………………c1

        BINARY_INSERTION_SORT ( A , L , R-1 )…………c2//R==2之前一直调用函数对前面的R-1个元素进行排序

    key = A[ R ]………………………………………………c3//待插入的值给key

    BINARY_INSERT ( A , L , R - 1 , key )………………c4//将A[ R ]插入前面已经排好的0~R-1序列中

//递归的插入排序主函数

BINARY_INSERT ( A , L , R , key )

    if L > R……………………………………………………c5

        A[ L] = key…………………………………………c6

        return………………………………………………c7//若左溢出则将key赋给溢出之前的位置,若右溢出则赋值给L=R+1这个溢出位,即未排序的那个数的位置不动

    else if key <= A[ ( L + R ) / 2]…………………………c8//若key值在二分点左侧则要将二分点右侧所有元素右移一位

        for i = R downto ( L + R ) / 2……………………c9

                A[ i + 1 ] = A [ i ]……………………………………c10

                BINARY_INSERT ( A , L , ( L + R ) / 2 , key )……c11//继续找key该呆的位置

    else BINARY_INSERT ( A , ( L + R ) / 2 , R , key )…………c12//若key值在二分点右侧则不做处理,继续迭代

//二分比较并移动较大项函数

鉴于计算过程太繁杂,手码的话要浪费大量时间,就直接给结果了_(:зゝ∠)_,其中k1~5都是用于替换c1~11组成的一次算式的常数。

  BINARY_INSERTION_SORT函数的递归式为:

    T1( n ) = k4 + T1( n - 1 ) + T2( n ),n>=2.

  BINARY_INSERT函数的递归式为:

    T2 ( n ) = k1 * n + k2 + T2 ( n - 1 ),n>1

    T2 ( 1 ) = k3,                                  n=1.

通式:(lg(n)代表以2为底,n的对数,书上有说明

T2( n ) = 2 * k1 * n + k2 * lg(n) - 2 * k1 +k3

T1( n ) = k1 * (n² + n - 2) + k2 * lg(n!) + k5 * ( n - 1 )//用斯特林公式将n!做近似处理,不懂的这里https://blog.csdn.net/SSYITwin/article/details/80111157

T1( n ) = k1 * n² + k2 * n *lg(n) + ( k1 - lg(e) *k2 + k5 ) *n +lg((2*π*n)½) -2 * k1 - k5

故将while替换后也不会对原插入排序的复杂度O(n²)造成多大影响,更不可能达到题目要求的O(n*lgn)。

但是这做法也做了对while的部分优化,优化了多少呢?有兴趣的同学请看下面。

将k1~k5的值代入原式(自己拿草稿纸写一下吧

k1= 0.5 * ( c9 + c10 + c11 )

k2= c5 + c8 + c9

k3= c5 + c6 + c7

k4= c1 + c2 + c3 + c4

k5= - k2 + k3 + k4

接下来将https://blog.csdn.net/gaint_moon_mystery/article/details/82289834这篇里的k1、k2的值也代入原式T(n)。(用书里第14~15页的代码与T(n)的通式比较也行。

对比两组代码中的相似部分,本文中n²的系数k1中包含了c10(自减)、c11(换位)、c12(调用自己),而书中n²的系数包含了c5(比较大小、判断是否溢出)、c6(换位)、c7(自减)。可见其中 自减 和 换位 两项没有被优化,而本文中的比较大小和判断是否溢出分别是c8(比较大小)、c5(判断是否溢出),他们分别属于,c8->(k2,k5),c5->(k2,k3,k5)。如果我们忽略小值,那么c8(比较大小)的时间复杂度为O(n*lgn),c5(判断是否溢出)的时间复杂度为O(n)。

如果把比较大小和判断是否溢出这两个判断语句拆开来算,那么这个改动对原插入排序排序算法的的优化点为,将“比较两数大小”由O(n²)降低到O(n*lgn),将“判断是否溢出”O(n²)降低到O(n),额外增添了“自己调用自己”复杂度为O(n²)。

全局优化为O(n²)-O(n*lgn)-O(n)。不知道“自己调用自己”这步的具体时长与另外两步有多大区别,好心前辈可以帮忙补充一下或指出我的错误,不然看起来好像还不如不优化_(:зゝ∠)_,谢谢大家,喜欢请点赞(>^ω^<)。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值