通过上述讨论,可以看出递归程序在执行时需要系统提供隐式栈这种数据结构来实现,对于 一般的递归过程,仿照递归算法执行过程中递归工作栈的状态变化可直接写出相应的非递归算法。
这种利用栈消除递归过程的步骤如下:
(1)设置一个工作栈存放递归工作记录(包括实参、 返回地址及局部变量等)。
(2)进入非递归调用入口(即被调用程序开始处) 将调用程序传来的实在参数和返回地址入 栈(递归程序不可以作为主程序,因而可认为初始是被某个调用程序调用。
(3)进入递归调用入口:当不满足递归结束条件时,逐层递归,将实参、 返回地址及局部变 量入栈,这一过程可用循环语句来实现一模拟递归分解的过程。
(4)递归结束条件满足,将到达递归出口的给定常数作为当前的函数值。
(5)返回处理:在栈不空的情况下,反复退出栈顶记录,根据记录中的返回地址进行题意规 定的操作,即逐层计算当前函数值,直至栈空为止一模拟递归求值过程。
通过以上步骤,可将任何递归算法改写成非递归算法。但改写后的非递归算法和原来比较起 来,结构不够清晰,可读性差,有的还需要经过一系列的优化,这里不再举例详述,具体示例参 见5.5.1节中二叉树中序遍历的非递归算法。
自己思路:
1、设置栈顶和栈
2、循环条件一般有两个以上,其中一个栈顶
二叉树中序遍历
#include<stdio.h>
#include<stdlib.h>
//栈顶,栈的值
typedef struct tree{
int value;
struct tree *left;
struct tree *right;
}Tree;
void d(Tree *t){
if(t){
d(t->left);
printf("%d\n",t->value);
d(t->right);
}
}
void gas(Tree *tr){
Tree *stack[10];
int i=-1; //栈无值
while(i>=0||tr){ //i+1标志还有多少个栈
if(tr){
i++;
stack[i]=tr;
tr=tr->left;
}
else{
printf("%d\n",stack[i]->value);
tr=stack[i]->right;
i--;
}
}
return;
}
int main(){
//构建树,简便写法
Tree *head=(Tree *)malloc(sizeof(Tree));
head->value=12;
head->left=NULL;
head->right=NULL;
Tree *a=(Tree *)malloc(sizeof(Tree));
a->value=11;
a->left=NULL;
a->right=NULL;
head->left=a;
Tree *b=(Tree *)malloc(sizeof(Tree));
b->value=10;
b->left=NULL;
b->right=NULL;
head->right=b;
//递归算法
// d(head);
//非递归算法
gas(head);
return 0;
}