如何用栈实现递归与非递归的转换
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
如何用栈实现递归与非递归的转换
一.为什么要学习递归与非递归的转换的实现方法?
1)并不是每一门语言都支持递归的.
2)有助于理解递归的本质.
3)有助于理解栈,树等数据结构.
二.递归与非递归转换的原理.
递归与非递归的转换基于以下的原理:所有的递归程序都可以用树结构表示出来.需要说明的是,
这个"原理"并没有经过严格的数学证明,只是我的一个猜想,不过在至少在我遇到的例子中是适用的.
学习过树结构的人都知道,有三种方法可以遍历树:前序,中序,后序.理解这三种遍历方式的递归和非
递归的表达方式是能够正确实现转换的关键之处,所以我们先来谈谈这个.需要说明的是,这里以特殊的
二叉树来说明,不过大多数情况下二叉树已经够用,而且理解了二叉树的遍历,其它的树遍历方式就不难
了.
1)前序遍历
a)递归方式:
[code:1:1f2a39cc2d]void preorder_recursive(Bitree T) /* 先序遍历二叉树的递归算法*/
{
if (T) {
visit(T); /* 访问当前结点*/
preorder_recursive(T->lchild); /* 访问左子树*/
preorder_recursive(T->rchild); /* 访问右子树*/
}
}[/code:1:1f2a39cc2d]
b)非递归方式
[code:1:1f2a39cc2d]void preorder_nonrecursive(Bitree T) /* 先序遍历二叉树的非递归算法*/
{
initstack(S);
push(S,T); /* 根指针进栈*/
while(!stackempty(S)) {
while(gettop(S,p)&&p) { /* 向左走到尽头*/
visit(p); /* 每向前走一步都访问当前结点*/
push(S,p->lchild);
}
pop(S,p);
if(!stackempty(S)) { /* 向右走一步*/
pop(S,p);
push(S,p->rchild);
}
}
}[/code:1:1f2a39cc2d]
2)中序遍历
a)递归方式
[code:1:1f2a39cc2d]void inorder_recursive(Bitree T) /* 中序遍历二叉树的递归算法*/ {
if (T) {
inorder_recursive(T->lchild); /* 访问左子树*/
visit(T); /* 访问当前结点*/
inorder_recursive(T->rchild); /* 访问右子树*/
}
}[/code:1:1f2a39cc2d]
b)非递归方式
[code:1:1f2a39cc2d]void inorder_nonrecursive(Bitree T)
{
initstack(S); /* 初始化栈*/
push(S, T); /* 根指针入栈*/
while (!stackempty(S)) {
while (gettop(S, p) && p) /* 向左走到尽头*/
push(S, p->lchild);
pop(S, p); /* 空指针退栈*/
if (!stackempty(S)) {
pop(S, p);
visit(p); /* 访问当前结点*/
push(S, p->rchild); /* 向右走一步*/
}
}
}[/code:1:1f2a39cc2d]
3)后序遍历
a)递归方式
[code:1:1f2a39cc2d]void postorder_recursive(Bitree T) /* 中序遍历二叉树的递归算法*/ {
if (T) {
postorder_recursive(T->lchild); /* 访问左子树*/
postorder_recursive(T->rchild); /* 访问右子树*/
visit(T); /* 访问当前结点*/
}
}[/code:1:1f2a39cc2d]
b)非递归方式
[code:1:1f2a39cc2d]typedef struct {
BTNode* ptr;
enum {0,1,2} mark;
} PMType; /* 有mark域的结点指针类型*/
void postorder_nonrecursive(BiTree T) /* 后续遍历二叉树的非递归算法*/ {
PMType a;
initstack(S); /* S的元素为PMType类型*/
push (S,{T,0}); /* 根结点入栈*/
while(!stackempty(S)) {
pop(S,a);
switch(a.mark)
{
case 0:
push(S,{a.ptr,1}); /* 修改mark域*/
if(a.ptr->lchild)
push(S,{a.ptr->lchild,0}); /* 访问左子树*/
break;
case 1: