中序遍历二叉树的非递归实现
- 之前的博客写了递归的实现,说白了也就是不断自己调用自身,保持左根右的顺序。只需写出整体逻辑结构,程序会自己递归复杂的过程,大体即为:
void inTraverseByRecur(Tree& T)
{
if(T)
{
inTraverseByRecur(T->lchild);
cout<<T->data;
inTraverseByRecur(T->rchild);
}
}
-
而非递归实现我采用了栈结构作辅助,因为中序遍历其为左根右,它本身遍历的特性可用不断的出栈进栈模拟。当我们以T为树的根结点时,要想做到中序遍历,需要以下几步:
①.若根结点T存在,将T压入栈中,若T->lchild为真(即T有左孩子),更新它的左孩子为根结点:即T=T->lchild,重复步骤①,直到一直往左走找不到左孩子为止(此时找到了中序序列的首结点),转至步骤②。
②.因为当前结点无左孩子,按照中序遍历左根右,则该结点出栈。若该结点有右孩子,则将右孩子视为根结点,转至步骤①,直到走到中序序列尽头,栈为空为止。 -
以下为完整代码,包含了栈结构,二叉树结点结构及它们的操作函数,递归及非递归的实现函数我都放在了里面。
-
这里有一些细节需要注意,传递指针和传递引用的区别,栈中的数据域元素存储的类型为结点结构。
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define STACK_INIT_SIZE 100 //栈的初始化容量
#define STACK_INC_SIZE 10 //栈的分配增量
typedef char ElementType; //二叉树的数据域元素类型
/*二叉树结点结构*/
typedef struct BiTree{
struct BiTree* lchild;
struct BiTree* rchild;
ElementType data;
}TreeNode,*Tree;
typedef Tree elemType; //栈存储的数据元素类型为二叉树结点结构
/*栈的数据结构*/
typedef struct{
elemType* base; //栈底指针
elemType* top; //栈顶指针
int stackSize; //当前已分配的栈总存储空间
}SqStack;
void initStack(SqStack& S); //构造空栈并初始化
void pushStack(SqStack& S,elemType data); //数据元素进栈
void popStack(SqStack& S); //数据元素出栈
int emptyStack(SqStack& S); //判断栈是否为空
void createBiTree(Tree& T); //创建并添加二叉树信息,录入方式为根左右
void inTraverseByRecur(Tree& T); //递归方式实现中序遍历二叉树
void inTraverseByNotRecur(Tree& T,SqStack& S); //非递归方式实现中序遍历二叉树()
elemType getTop(SqStack& S); //返回栈顶元素
void initStack(SqStack& S)
{
S.base=(elemType*)malloc(STACK_INIT_SIZE * sizeof(elemType));
if(!S.base) exit(1);
S.top=S.base;
S.stackSize=STACK_INIT_SIZE;
}
void pushStack(SqStack& S,elemType data)
{
if(S.top-S.base>=S.stackSize) //栈满,扩充容量
{
S.base=(elemType*)realloc(S.base,(S.stackSize+STACK_INC_SIZE) * sizeof(elemType));
if(!S.base) exit(1);
S.top=S.base+S.stackSize; //栈顶改变
S.stackSize+=STACK_INC_SIZE;
}
*S.top=data;
S.top++;
}
void popStack(SqStack& S)
{
if(S.top!=S.base)
{
S.top--;
}
}
int emptyStack(SqStack& S)
{
//栈空则返回0
if(S.base==S.top)
{
return 0;
}
else
{
return 1;
}
}
elemType getTop(SqStack& S)
{
return *(S.top-1);
}
void createBiTree(Tree& T)
{
ElementType ch;
cin>>ch;
if(ch=='#') T=NULL;
else
{
//if(!(T=(TreeNode*)malloc(sizeof(TreeNode))))
if(!(T=(Tree)malloc(sizeof(TreeNode))))
{
cout<<"malloc fail"<<endl;
exit(0);
}
T->data=ch;
createBiTree(T->lchild);
createBiTree(T->rchild);
}
}
//实现递归方式的中序遍历
void inTraverseByRecur(Tree& T)
{
//-+a##*b##-c##d##/e##f##
if(T)
{
inTraverseByRecur(T->lchild);
cout<<T->data;
inTraverseByRecur(T->rchild);
}
}
//实现非递归方式的中序遍历
void inTraverseByNotRecur(Tree& T,SqStack& S)
{
Tree p;
p=T;
//若栈为空,emptyStack(S)返回为0
while(p||emptyStack(S)) //只有当结点为空,栈也为空时退出循环
{
while(p) //结点不为空时,一直找左孩子
{
pushStack(S,p);
p=p->lchild;
}
//找不到左孩子时,若栈也不为空,则栈顶元素出栈,将栈顶元素的右孩子再作为根结点,继续找左孩子
//这样持续下去最终会按照非递归的方式输出左根右
if(emptyStack(S))
{
p=getTop(S);
cout<<p->data;
popStack(S);
p=p->rchild;
}
}
}
int main()
{
SqStack S; //定义栈S
Tree T1; //定义二叉树的根结点
initStack(S); //初始化栈S
createBiTree(T1); //创建并添加二叉树信息
inTraverseByRecur(T1); //递归方式中序遍历二叉树
cout<<endl;
inTraverseByNotRecur(T1,S);//非递归方式中序遍历二叉树
return 0;
}