编程珠玑习题第四章第九题的感想

来源:互联网 发布:office淘宝验证码弹出 编辑:程序博客网 时间:2024/05/22 11:08

如题:

 

将如下递归代码改写成非递归形式

int exp(int x, int n) {

     if ( n == 0) {

      return 1;

  } else if (n % 2 == 0) {

          return exp (x, n / 2) * exp(x, n / 2);-------------------------(1)

 } else {

    return x * exp(x,n-1);---------------------(2)

}

}

 

分析:

  1. 递归处理式(1),(2)是按n的奇偶性来分别处理的,并且对n为奇数时要进行的下一个子问题中的n = n-1,由n为奇数知,n= n-1必定为偶数,所以(2)执行后的下一步递归式中执行的必定是(1)。
  2. (1)执行的下一步递归是n = n / 2; 由于n为偶数,所以必定可以整除。然而,由式(1)引发的下一步递归究竟到达(1)(2)中的哪一个就要看n/2的奇偶性了
  3. 将n表示成二进制数,n为奇数时执行(2)相当于将n末尾的1清掉,接着执行递归(1)得到n>>1的递归参数,再下一步执行(1)还是(2)得看n>>1的末位是否为1了(即n>>1的奇偶性)。
  4. 具体分析一个实例:n = 7时, 上述递归过程计算x^7可以看成 x*(x*(x)^2)^2, 递归的实际计算过程如下:(x), (x) ^2, x*(x)^2 ,(x*(x)^2)^2, x*(x*(x)^2)^2,递归的调用轨迹可以用(2)(1)(2)(1)(2)然后到"return 1“,一步步退出递归栈了。我们可以发现以上这两个序列和n用二进制表示的莫大关联:7 = 0111B,   0111B 末位为1 因此开始调用递归式(2), 由分析1知,(2)调用后的下一步递归为(1),则011 = (0111-1)/ 2; 再下一步递归式按照011 % 2==1 知应该为(2)。。。。。这样就和(2)(1)(2)(1)(2)相吻合。
  5. 综上所示,我们完全可以根据n的二进制表示中各位的值(0或者1)来推断递归的轨迹,从而写出上述递归程序的非递归算法:

result = 1;

 if( n == 0)

return 1;

tag = 31;

while( (1 << tag) & n ! = 0) tag--;//找到n的二进制表示中最高位所在的位号

while(tag >=0) {

            if ((1<<tag) & n !=0) {

                   result *= x;

                   result = result * result;

           } else {

                result = result * result; 

         }

        tag--;

}

return result;

 

原创粉丝点击