详细解释递归原理

一直以来对于递归原理都不是很了解,最近找实习非得要学习了,于是今天好好的研究了一下,这里以《剑指offer》上面第93页递归的例子来进行分析。
问题是:求a的n次方。
下面是一个比较简单的求法的公式:

a n = { a n / 2 a n / 2 n为偶数 a ( n 1 ) / 2 a ( n 1 ) / 2 a n为奇数

由以上公式就可以写出下面的代码:

double Power(double base, unsigned int exponent) {
    // 递归的终止条件
    if (exponent == 0)
        return 1;
    if (exponent == 1)
        return base;
    // 递归进栈和出栈处    
    double result = PowerExponent(base, exponent >> 1);
    result *= result;
    if ((exponent & 0x1)== 1) {

        result *= base;
        cout << result << endl;
    }
    return result;
}

这里拿一个简单的例子来进行分析:
假设我们调用函数为:Power(3, 15);

1、Power(3, 15)中base=3,exponent=15,递归的终止条件均不满足,进入到 递归进栈和出栈处,此时result = Power(3, 7)(此处exponent >> 1的运算过程为:exponent=15,用二进制表示为1111,右移一位即为0111,表示7,所以exponent变为7,下同)进栈;
2、Power(3, 7)中base=3,exponent=7,递归的终止条件均不满足,进入到递归进栈和出栈处,此时result = Power(3, 3)进栈;
3、Power(3, 3)中base=3,exponent=3,递归的终止条件均不满足,进入到递归进栈和出栈处,此时result = Power(3, 1)进栈;

此时exponent=1,递归的终止条件第二个if条件满足(注意此处即使有两个终止条件也不要继续往下计算,因为函数遇到return就会终止,每个函数只有一个return),因此全部进栈完毕,开始出栈

4、Power(3, 1)出栈,base=3,exponent=1,可以看做执行函数如下:

double Power(double base, unsigned int exponent) {
    if (exponent == 1)
        return base;
}

即此时在递归进栈和出栈处result = Power(3, 1) = base = 3

5、Power(3, 3)出栈,base=3,exponent=3,可以看做执行函数如下:

double Power(double base, unsigned int exponent) {
    // 即为将Power(3, 1)代入函数中来计算Power(3, 3)的值
    double result = Power(3, 1);
    result *= result;
    if ((exponent & 0x1)== 1) {

        result *= base;
        cout << result << endl;
    }
    return result;
}

即此时在递归进栈和出栈处result = Power(3, 3) = Power(3, 1)* Power(3, 1) * base = 3*3*3 = 27(最后乘base因为exponent=3满足if的条件,其中if的条件中(exponent & 0x1)指的是将exponent与八进制的1即用二进制表示为0001作位与运算,即判断exponent的二进制形式最后一位是否为1,即判断exponent是否为奇数,下同)

6、Power(3, 7)出栈,base=3,exponent=7,可以看做执行函数如下:

double Power(double base, unsigned int exponent) {
    // 即为将Power(3, 3)代入函数中来计算Power(3, 7)的值
    double result = Power(3, 5);
    result *= result;
    if ((exponent & 0x1)== 1) {

        result *= base;
        cout << result << endl;
    }
    return result;
}

即此时在递归进栈和出栈处result = Power(3, 7) = Power(3, 3)* Power(3, 3) * base = 27*27*3 = 2187(最后乘base因为exponent=3满足if的条件)

7、最后计算Power(3, 15),base=3,exponent=15,可以看做执行函数如下:

double Power(double base, unsigned int exponent) {
    // 即为将Power(3, 7)代入函数中来计算Power(3, 15)的值
    double result = Power(3, 7);
    result *= result;
    if ((exponent & 0x1)== 1) {

        result *= base;
        cout << result << endl;
    }
    return result;
}

即此时result = Power(3, 15) = Power(3, 7)* Power(3, 7) * base = 2187*2187*3 = 14348907(最后乘base因为exponent=3满足if的条件)

(注意出栈的4,5,6,7步中实际的运行是会重新运行一遍整个函数的,此处为了强调递归的终止和递归出栈后的执行部分所以将没有运行的代码段部分省略掉了)

规律总结

从上面的步骤分析可以看出,递归在没有满足递归终止条件的时候,将每次递归的中间值都进栈,因此每一次递归的过程中相当于在递归进栈和出栈处打了一个断点,然后在第一次满足递归终止条件时将会开始出栈,出栈实际上是从每一次停止的断点处开始执行,将这一次递归得到的值返回给上一次递归,并以此继续进行下去,下面几个经典的递归例子可以仿照上面的分析过程进行分析。

// 计算阶乘
long factorial_recursion(int n){

    if(n <= 0)
        return 1;

    else
        return n * factorial_recursion(n-1);
}
// 计算Fibonacci数列
long long Fibonacci(unsigned int n){

    if (n <= 0) 
        return 0;
    if (n == 1) 
        return 1;

    return Fibonacci(n-1) + Fibonacci(n - 2);
}

猜你喜欢

转载自blog.csdn.net/sinat_28731575/article/details/79807647
今日推荐