递归转非递归学习二:求斐波那契数列F(N)的值

来源:互联网 发布:千帆网络信息传媒 编辑:程序博客网 时间:2024/05/17 10:09

上《数据结构》的网络课程学习了递归转非递归的机械式转换的方法之后,

先练习写了N的阶乘方法转非递归(模拟栈)的代码,然后试着将斐波那契数列求F(N)的值的过程(模拟栈)转化为非递归:

#include <iostream>#include <stack>using namespace std;// (1). 设置工作栈中元素的结构体struct Datatype{    int n;          // 当前输入数据n    int fn;         // FibonacciSequence(n)的返回值    int fn_1;       // 局部变量FibonacciSequence(n-1)的值    int fn_2;       // 局部变量FibonacciSequence(n-2)的值    int retAddr;    // 模仿返回地址,调用第i个递归函数的标示符为i(i=1,2,3,...,t);t+1为栈底标示符,也是结束符};int FibonacciSequence(int N){    // (3). 增加非递归入口    // 初始化    Datatype currArea, areaTemp;    // 当前栈中的元素,和一个临时元素    currArea.n = N;                 // 当前元素的n值    currArea.fn = 0;    currArea.fn_1 = 0;    currArea.fn_2 = 0;    currArea.retAddr = 3;           // 栈底"监视哨",作为整个循环的结束标志    int retResult = 0;              // 存储最终结果的变量    // (1). 设置一个工作栈    stack<Datatype> s;    s.push(currArea);// (2). 设置t+2个语句标号(t为递归函数内调用本身的次数,编号分别为0,1,...,t+1)// 由于例子中函数两次调用其本身,所以t=2label0:                         // 递归总入口    areaTemp = s.top();         // 获取栈顶元素的值,用来判断n的值    if (currArea.n <= 1)        // 判断n的值小于等1,直接计算    {        s.pop();                // 弹出栈顶元素,赋予新值之后再入栈        areaTemp.fn = currArea.n;   // n=0或者1时,FibonacciSequence(n) = n;        s.push(areaTemp);        goto label3;            // 转向递归调用总出口    }    // 依次将FibonacciSequence(n-1)...FibonacciSequence(1)入栈    currArea.n--;    currArea.fn = 0;    currArea.fn_1 = 0;    currArea.fn_2 = 0;    currArea.retAddr = 1;   // 第一处递归FibonacciSequence(n-1)的入口    s.push(currArea);    goto label0;// (4). 替换第i(i=1...t)个递归规则label1:                     // 第一处递归函数的出口    areaTemp = s.top();    s.pop();    currArea = s.top();    s.pop();    currArea.fn_1 = areaTemp.fn;    // 获得FibonacciSequence(n-1)的值,之后再入栈    s.push(currArea);    currArea.n = currArea.n - 2;    currArea.retAddr = 2;           // 第二处递归FibonacciSequence(n-2)    s.push(currArea);    goto label0;                    // 进入递归总入口,为了计算第二处递归FibonacciSequence(n-2)的值label2:                             // 第二个递归调用的出口    areaTemp = s.top();    s.pop();    currArea = s.top();    s.pop();    currArea.fn_2 = areaTemp.fn;    // 获得FibonacciSequence(n-2)的值    currArea.fn = currArea.fn_1 + currArea.fn_2; // 直接计算FibonacciSequence(n)的值    s.push(currArea);    goto label3;label3:                             // 递归调用总出口,(6). 标号为t+1的语句格式    areaTemp = s.top();    switch(areaTemp.retAddr)    {    case 1:        goto label1;        break;    case 2:        goto label2;        break;    case 3:                         // 如果获得的是栈底元素,结束整个循环        s.pop();                    // 退栈,清空栈        retResult = areaTemp.fn;        break;    default:        cerr << "error label number in stack!" << endl;        break;    }    return retResult;}// 尾递归转非递归,用循环结构求斐波那契数列int FibonacciSequence2(int n){    if (n <= 1)        return n;    long fib1 = 0, fib2 = 1;    for (int i = 2; i <= n; i++)    {        fib2 = fib1 + fib2;    // 得到新Fib2(n)的值        fib1 = fib2 - fib1;    // 得到新Fib2(n-1)的值    }    return fib2;}int main(){    int number;    cin >> number;    cout << FibonacciSequence(number) << endl;    cout << FibonacciSequence2(number) << endl;    return 0;}

原创粉丝点击