二叉树先序中序后序的递归及非递归遍历

Posted 希声lx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树先序中序后序的递归及非递归遍历相关的知识,希望对你有一定的参考价值。

昨天写数据结构关于二叉树的几种顺序的递归及非递归遍历的程序,后续遍历有点难。现在把程序给大家参考一下,有些思路参考自:http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html的思路。

一、先序遍历二叉树

   1.递归遍历

    每次先判断是否为空树,若不是则访问根节点,然后左子树,最后右子树。

void PreOrderTraverse1(BiTree T)
{//先序遍历二叉树T的递归算法
// cout<<"二叉树先序递归遍历\\n";
if(T) //若二叉树非空
{
cout<<T->data; //访问根节点
PreOrderTraverse1(T->lchild); //遍历左孩子
PreOrderTraverse1(T->rchild); //遍历右孩子
}

}

复制代码

  2.非递归遍历

   判断栈是否为空或子树为空,若不为空,就访问左孩子入栈,直至左孩子为空,若左孩子为空,就出栈,然后访问右孩子,入栈,就这样不断的循环。

复制代码

void PreOrderTraverse2(BiTNode *T)
{//先序遍历二叉树T的非递归算法
// cout<<"二叉树先序非递归遍历\\n";
StackNode *S;
BiTNode *p;
S=NULL;
S=InitStack(S);
p=T;

// cout<<"pre1.1\\n";
if(p==NULL)
{
// cout<<"pre1.2\\n";
cout<<"树为空\\n";
return;
}
// cout<<"pre1.3\\n";
while(p||!StackEmpty(S))
{

// cout<<"pre1.4\\n";
if(p)
{
// cout<<"pre1.5\\n";
Push(S,p);
cout<<p->data;
p=p->lchild;
}
else
{
// cout<<"pre1.6\\n";
Pop(S,p);
p=p->rchild;
}
}
// cout<<"pre1.7\\n";
}

复制代码

 

二、中序遍历二叉树

     1.递归遍历

      每次先判断树是否为空,若不为空,则访问左子树,然后根子树,最后右子树。

复制代码

void InOrderTraverse1(BiTree T)
{//中序遍历二叉树T的递归算法
// cout<<"二叉树中序递归遍历\\n";
if(T) //若二叉树非空
{
InOrderTraverse1(T->lchild); //遍历左孩子
cout<<T->data; //访问根节点
InOrderTraverse1(T->rchild); //遍历右孩子
}


}


复制代码

    2.非递归遍历

    思路基本和先序差不多,只是输出数据的时候不一样。判断栈和树是否为空,若不,则判断树是否为空,不为继续将左子树进栈,若为空,则出栈,输出数据,然后访问右子树。

复制代码

void InOrderTraverse2(BiTree &T)
{//中序遍历二叉树T的非递归算法
// cout<<"二叉树中序非递归遍历\\n";
StackNode *S;
BiTNode *p;
S=InitStack(S);
p=T;
while(p||!StackEmpty(S))
{
if(p)
{
Push(S,p);
p=p->lchild;
}
else
{
Pop(S,p);
cout<<p->data;
p=p->rchild;
}
}
}


复制代码

三、后序遍历二叉树

    1.递归遍历

    先判断树是否为空,若不为,先左子树,后右子树,然后根节点。

复制代码

void LastOrderTraverse1(BiTree T)
{//后序遍历二叉树T的递归算法
// cout<<"二叉树后序递归遍历\\n";
if(T) //若二叉树非空
{
LastOrderTraverse1(T->lchild); //遍历左孩子
LastOrderTraverse1(T->rchild); //遍历右孩子
cout<<T->data; //访问根节点
}


}


复制代码

    2.非递归遍历

     要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

复制代码

void LastOrderTraverse2(BiTNode *T)
{//后序遍历二叉树T的非递归算法
// cout<<"二叉树后序非递归遍历\\n";
StackNode *S;
BiTNode *p,*cur;
S=InitStack(S);
p=T;
p=NULL;cur=NULL;
Push(S,T);
while(!StackEmpty(S))
{
cur=NULL;
GetTop(S,cur);
if((cur->lchild==NULL && cur->rchild==NULL) || (p!=NULL &&(p==cur->lchild || p==cur->rchild)))
{
cout<<cur->data;
p=cur;
Pop(S,cur);

}
else
{
if(cur->rchild!=NULL)
{
Push(S,cur->rchild);
}
if(cur->lchild!=NULL)
{
Push(S,cur->lchild);
}
}
}
}


复制代码

 

 

下面是完整的程序:

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;


typedef struct BiTNode //树的结点
{
char data; //节点数据域
struct BiTNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;

typedef BiTNode *SElemType;

typedef struct StackNode //栈的结点
{
SElemType data;
StackNode *next;
}StackNode;

StackNode *InitStack(StackNode *S)
{
S=(StackNode *)malloc(sizeof(StackNode));
if(S==NULL)
{
cout<<"内存不足,不能分配栈\\n";
exit(0);
}
S->next=NULL;
return(S);
}

int StackEmpty(StackNode *S)
{
if(S->next==NULL)
{
return(1);
}
return(0);
}

void Push(StackNode *S,SElemType data)
{
StackNode *p;
p = (StackNode *)malloc(sizeof(StackNode));
if(p==NULL)
{
cout<<"内存不足,不能分配栈\\n";
exit(0);
}
p->data=data;
p->next=S->next;
S->next=p;

}

void Pop(StackNode *S,SElemType &data)
{
StackNode *p;
if(S->next==NULL)
{
cout<<"栈为空,无返回值\\n";
}
p=S->next;
data=p->data;
S->next=p->next;
free(p);

}

int GetTop(StackNode *S,SElemType &data)
{
if(S->next!=NULL)
{
data=S->next->data;
return(1);
}
else
{
return(0);
}
}

 

BiTNode *InitTree(BiTNode *T)
{
char data;
cin>>data;
if(\'#\'==data)
{
T=NULL;
}
else
{
T=(BiTNode *)malloc(sizeof(BiTNode));
T->data=data;
T->lchild=InitTree(T->lchild);
T->rchild=InitTree(T->rchild);

}
return(T);
}

void PreOrderTraverse1(BiTree T)
{//先序遍历二叉树T的递归算法
// cout<<"二叉树先序递归遍历\\n";
if(T) //若二叉树非空
{
cout<<T->data; //访问根节点
PreOrderTraverse1(T->lchild); //遍历左孩子
PreOrderTraverse1(T->rchild); //遍历右孩子
}

}

void InOrderTraverse1(BiTree T)
{//中序遍历二叉树T的递归算法
// cout<<"二叉树中序递归遍历\\n";
if(T) //若二叉树非空
{
InOrderTraverse1(T->lchild); //遍历左孩子
cout<<T->data; //访问根节点
InOrderTraverse1(T->rchild); //遍历右孩子
}

}

void LastOrderTraverse1(BiTree T)
{//后序遍历二叉树T的递归算法
// cout<<"二叉树后序递归遍历\\n";
if(T) //若二叉树非空
{
LastOrderTraverse1(T->lchild); //遍历左孩子
LastOrderTraverse1(T->rchild); //遍历右孩子
cout<<T->data; //访问根节点
}

}


void PreOrderTraverse2(BiTNode *T)
{//先序遍历二叉树T的非递归算法
// cout<<"二叉树先序非递归遍历\\n";
StackNode *S;
BiTNode *p;
S=NULL;
S=InitStack(S);
p=T;

// cout<<"pre1.1\\n";
if(p==NULL)
{
// cout<<"pre1.2\\n";
cout<<"树为空\\n";
return;
}
// cout<<"pre1.3\\n";
while(p||!StackEmpty(S))
{

// cout<<"pre1.4\\n";
if(p)
{
// cout<<"pre1.5\\n";
Push(S,p);
cout<<p->data;
p=p->lchild;
}
else
{
// cout<<"pre1.6\\n";
Pop(S,p);
p=p->rchild;
}
}
// cout<<"pre1.7\\n";
}

 

void InOrderTraverse2(BiTree &T)
{//中序遍历二叉树T的非递归算法
// cout<<"二叉树中序非递归遍历\\n";
StackNode *S;
BiTNode *p;
S=InitStack(S);
p=T;
while(p||!StackEmpty(S))
{
if(p)
{
Push(S,p);
p=p->lchild;
}
else
{
Pop(S,p);
cout<<p->data;
p=p->rchild;
}
}
}

void LastOrderTraverse2(BiTNode *T)
{//后序遍历二叉树T的非递归算法
// cout<<"二叉树后序非递归遍历\\n";
StackNode *S;
BiTNode *p,*cur;
S=InitStack(S);
p=T;
p=NULL;cur=NULL;
Push(S,T);
while(!StackEmpty(S))
{
cur=NULL;
GetTop(S,cur);
if((cur->lchild==NULL && cur->rchild==NULL) || (p!=NULL &&(p==cur->lchild || p==cur->rchild)))
{
cout<<cur->data;
p=cur;
Pop(S,cur);

}
else
{
if(cur->rchild!=NULL)
{
Push(S,cur->rchild);
}
if(cur->lchild!=NULL)
{
Push(S,cur->lchild);
}
}
}
}

 

int main()
{
BiTNode *Tree;
Tree=NULL;
cout<<"按照层次遍历建立树,\'#\'表示树为空\\n" <<endl;
cout<<"请输入要建立的树:"<<endl;
cout<<"\\n";
Tree=InitTree(Tree);
int choose;
cout<<"请输入0(表示递归遍历)或1(表示非递归遍历)\\n";
cin>>choose;
if(choose==0)
{
cout<<"二叉树先序递归遍历\\n";
PreOrderTraverse1(Tree);
cout<<endl;
cout<<"二叉树中序递归遍历\\n";
InOrderTraverse1(Tree);
cout<<endl;
cout<<"二叉树后序递归遍历\\n";
LastOrderTraverse1(Tree);
cout<<endl;
}
else if(choose==1)
{
cout<<"二叉树先序非递归遍历\\n";
PreOrderTraverse2(Tree);
cout<<endl;
cout<<"二叉树中序非递归遍历\\n";
InOrderTraverse2(Tree);
cout<<endl;
cout<<"二叉树后序非递归遍历\\n";
LastOrderTraverse2(Tree);
cout<<endl;
}
else
{
cout<<"输入错误\\n"<<endl;
}
return 0;
}

 

 

 

以上是关于二叉树先序中序后序的递归及非递归遍历的主要内容,如果未能解决你的问题,请参考以下文章

二叉树先序中序后序遍历 递归与非递归 Python实现

C语言数据结构,急求在线二叉树先序中序后序递归遍历

二叉树先序中序后序遍历 递归与非递归 Python实现

二叉树问题:递归方式实现二叉树先序中序后序遍历

二叉树先序中序后序遍历的非递归实现

用递归算法先序中序后序遍历二叉树