主题:[原创]手工递归一例 for N!
本程序是把求阶乘的递归算法,改成手工执行
[原题]
int fib (int n)
{
if (n == 1) return 1;
return n * fib (n - 1);
}
[new]
#include <stdio.h>
struct {
int ret, n, flag; /*ret返回域此例无用,flag是递归进度标志*/
} stack [201]; /*函数栈*/
int top = 0; /*0单元未用,1号位做栈底,top指向栈顶*/
int fib (int n)
{
int res;
++top;
stack [top].ret = 0;
stack [top].n = n;
stack [top].flag = 1; /*初始进栈*/
while (top > 0) { /*栈非空循环*/
if (stack[top].n == 1) {
res = 1;
stack[--top].flag--;
} /*同"if (n == 1) return 1;"*/
else if (stack[top].flag == 1) {
++top;
stack[top].ret = 0;
stack[top].n = stack[top-1].n - 1;
stack[top].flag= 1;
} /*同"n * fib (n - 1)"*/
else if (stack[top].flag == 0) {
res *= stack[top].n;
stack[--top].flag--;
} /*同return*/
}
return res;
}
int main (void)
{
printf ("%d\n", fib (4)); /*求4!*/
getch ();
return 0;
}
通过上一个问题《return i++》理解了return的实际过程。在本例中return分3部分:保存返回值;函数退栈;提示外层函数继续执行(新栈顶flag--)。
关键是flag这个调度标志不好理解。有的函数不只1次递归,像hanoi,在一层里面两次调用自己。那么如何判断何时进行下一个递归呢?就需要flag了,进行完一次调用后flag--,当flag==0时退栈。这是纯粹的对递归过程的模仿,还算不上好的非递归算法,但是可对任何递归进行同样的转化。
更详细的讨论见:euclid.99blog.com
[原题]
int fib (int n)
{
if (n == 1) return 1;
return n * fib (n - 1);
}
[new]
#include <stdio.h>
struct {
int ret, n, flag; /*ret返回域此例无用,flag是递归进度标志*/
} stack [201]; /*函数栈*/
int top = 0; /*0单元未用,1号位做栈底,top指向栈顶*/
int fib (int n)
{
int res;
++top;
stack [top].ret = 0;
stack [top].n = n;
stack [top].flag = 1; /*初始进栈*/
while (top > 0) { /*栈非空循环*/
if (stack[top].n == 1) {
res = 1;
stack[--top].flag--;
} /*同"if (n == 1) return 1;"*/
else if (stack[top].flag == 1) {
++top;
stack[top].ret = 0;
stack[top].n = stack[top-1].n - 1;
stack[top].flag= 1;
} /*同"n * fib (n - 1)"*/
else if (stack[top].flag == 0) {
res *= stack[top].n;
stack[--top].flag--;
} /*同return*/
}
return res;
}
int main (void)
{
printf ("%d\n", fib (4)); /*求4!*/
getch ();
return 0;
}
通过上一个问题《return i++》理解了return的实际过程。在本例中return分3部分:保存返回值;函数退栈;提示外层函数继续执行(新栈顶flag--)。
关键是flag这个调度标志不好理解。有的函数不只1次递归,像hanoi,在一层里面两次调用自己。那么如何判断何时进行下一个递归呢?就需要flag了,进行完一次调用后flag--,当flag==0时退栈。这是纯粹的对递归过程的模仿,还算不上好的非递归算法,但是可对任何递归进行同样的转化。
更详细的讨论见:euclid.99blog.com