递归与非递归转换的基础知识是可以正确理解三种树的遍历方法:前序,中序和后序,第一篇就是关于这三种遍历方法的递归和 非递归算法。 如何用栈实现递归与非递归的转换(一)三种遍历树的算法 一.为何要学习递归与非递归的转换的实现方法? 1)并非每一门语言都支持递归的. 2)有助于理解递归的本质. 3)有助于理解栈,树等数据结构. 二.三种遍历树的递归和非递归算法 递归与非递归的转换基于如下的原理:全部的递归程序均可以用树结构表示出来.须要说明的是,这个"原理"并无通过严格的 数学证实,只是个人一个猜测,不过在至少在我遇到的例子中是适用的.学习过树结构的人都知道,有三种方法能够遍历树:前序,中序 ,后序.理解这三种遍历方式的递归和非递归的表达方式是可以正确实现转换的关键之处,因此咱们先来谈谈这个.须要说明的是,这里 以特殊的二叉树来讲明,不过大多数状况下二叉树已经够用,并且理解了二叉树的遍历,其它的树遍历方式就不难。 了. 1)前序遍历 a)递归方式: void preorder_recursive(Bitree T) /* 先序遍历二叉树的递归算法 */ { if (T) { visit(T); /* 访问当前结点 */ preorder_recursive(T->lchild); /* 访问左子树 */ preorder_recursive(T->rchild); /* 访问右子树 */ } } b)非递归方式 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); } } } 2)中序遍历 a)递归方式 void inorder_recursive(Bitree T) /* 中序遍历二叉树的递归算法 */ { if (T) { inorder_recursive(T->lchild); /* 访问左子树 */ visit(T); /* 访问当前结点 */ inorder_recursive(T->rchild); /* 访问右子树 */ } } b)非递归方式 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); /* 向右走一步 */ } } } 3)后序遍历 a)递归方式 void postorder_recursive(Bitree T) /* 中序遍历二叉树的递归算法 */ { if (T) { postorder_recursive(T->lchild); /* 访问左子树 */ postorder_recursive(T->rchild); /* 访问右子树 */ visit(T); /* 访问当前结点 */ } } b)非递归方式 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: push(S,{a.ptr,2}); /* 修改mark域 */ if(a.ptr->rchild) push(S,{a.ptr->rchild,0}); /* 访问右子树 */ break; case 2: visit(a.ptr); /* 访问结点 */ } } }