您的位置:首页 > 编程语言

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

2012-12-28 14:42 239 查看

如题:



 

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

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),(2)是按n的奇偶性来分别处理的,并且对n为奇数时要进行的下一个子问题中的n = n-1,由n为奇数知,n= n-1必定为偶数,所以(2)执行后的下一步递归式中执行的必定是(1)。
(1)执行的下一步递归是n = n / 2; 由于n为偶数,所以必定可以整除。然而,由式(1)引发的下一步递归究竟到达(1)(2)中的哪一个就要看n/2的奇偶性了
将n表示成二进制数,n为奇数时执行(2)相当于将n末尾的1清掉,接着执行递归(1)得到n>>1的递归参数,再下一步执行(1)还是(2)得看n>>1的末位是否为1了(即n>>1的奇偶性)。
具体分析一个实例: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)相吻合。
综上所示,我们完全可以根据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;

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 算法