树的遍历
包括先序遍历,中序遍历,后序遍历和层次遍历(递归实现和非递归实现)以及求叶子数和数的高度;
#include"iostream"
#include"cstdio"
#include"stdlib.h"
#include"stack"
#include"queue"
using namespace std;
typedef struct node
{
char data;
node *lchild;
node *rchild;
} Bnode;
typedef Bnode *BTree;
typedef struct
{
Bnode *node;
int flag;
}DataType;
BTree CreatBinTree()
{
BTree t;
char ch;
ch=getchar();
if(ch=='#')
t=NULL;
else
{
t=(Bnode *)malloc(sizeof(Bnode));
t->data=ch;
t->lchild=CreatBinTree();
t->rchild=CreatBinTree();
}
return t;
}
void PreOrder1(BTree t)//树的递归实现先序遍历
{
if(t)
{
cout<<(t->data)<<' ';
PreOrder1(t->lchild);
PreOrder1(t->rchild);
}
}
void InOrder1(BTree t)//树的递归实现中序遍历
{
if(t)
{
InOrder1(t->lchild);
cout<<(t->data)<<' ';
InOrder1(t->rchild);
}
}
void PostOrder1(BTree t)//树的递归实现后序遍历
{
if(t)
{
PostOrder1(t->lchild);
PostOrder1(t->rchild);
cout<<(t->data)<<' ';
}
}
void PreOrder(BTree t)//树的非递归实现先序遍历
{
printf("树的非递归实现先序遍历:");
stack<Bnode *> S;
BTree p;
p=t;
while(p||!S.empty())
{
if(p)
{
cout<<p->data<<' ';
S.push(p);
p=p->lchild;
}
else
{
p=S.top();
S.pop();
p=p->rchild;
}
}
printf("\n");
}
void InOrder(BTree t)//树的非递归实现中序遍历
{
printf("树的非递归实现中序遍历:");
stack<Bnode *> S;
BTree p;
p=t;
while(p||!S.empty())
{
if(p)
{
S.push(p);
p=p->lchild;
}
else
{
p=S.top();
S.pop();
cout<<p->data<<' ';
p=p->rchild;
}
}
printf("\n");
}
void PostOrder(BTree t)//树的非递归实现后序遍历(双栈)
{
printf("树的非递归实现后序遍历(双栈):");
stack<Bnode *> S1;
stack<Bnode *> S2;
BTree p;
p=t;
while(p||!S2.empty())
{
if(p)
{
S1.push(p);
S2.push(p);
p=p->rchild;
}
else
{
p=S2.top();
S2.pop();
p=p->lchild;
}
}
while(!S1.empty())
{
p=S1.top();
S1.pop();
cout<<(p->data)<<' ';
}
printf("\n");
}
void Level(BTree t)//层次遍历
{
queue<Bnode *> S3;
Bnode *p;
p=t;
cout<<(p->data)<<' ';
S3.push(p);
while(!S3.empty())
{
p=S3.front();
S3.pop();
if(p->lchild!=NULL)
{
cout<<(p->lchild->data)<<' ';
S3.push(p->lchild);
}
if(p->rchild!=NULL)
{
cout<<(p->rchild->data)<<' ';
S3.push(p->rchild);
}
}
}
int Height(BTree t)//求树的高度
{
int h1,h2;
if(t==NULL)
return 0;
else
{
h1=Height(t->lchild);
h2=Height(t->rchild);
if(h1>h2)
return h1+1;
else
return h2+1;
}
}
int Num_leave(BTree t)//求树的叶子数
{
queue<Bnode *> S3;
int num=0,flag;
Bnode *p;
p=t;
S3.push(p);
while(!S3.empty())
{
flag=1;
p=S3.front();
S3.pop();
if(p->lchild!=NULL)
{
flag=0;
S3.push(p->lchild);
}
if(p->rchild!=NULL)
{
flag=0;
S3.push(p->rchild);
}
if(flag)
num++;
}
return num;
}
int main()
{
BTree t;
printf("请输入数据\n");
t=CreatBinTree();
printf("创建成功\n");
printf("先序遍历(递归):");
PreOrder1(t);
printf("\n");
printf("中序遍历(递归):");
InOrder1(t);
printf("\n");
printf("后序遍历(递归):");
PostOrder1(t);
printf("\n");
printf("层次遍历:");
Level(t);
printf("\n");
PreOrder(t);
InOrder(t);
PostOrder(t);
printf("树的高度:%d\n",Height(t));
printf("叶子数:%d\n",Num_leave(t));
return 0;
}
//ABD#G###CE##FH###
代码的最后给的是一个输入的例子,按照先序遍历的顺序进行输入的,并补全,例如下图就是程序最后给的例子,其他位置用#补全
现在说一说先序遍历,后序遍历和中序遍历是啥吧?
简单的说一下,
先序遍历:若树不为空先访问根节点,接着访问左子树,右子树,访问左右子树是和遍历整个树是一样的;
中序遍历:若树非空,中序遍历左子树,访问根节点,接着访问右子树;
后序遍历:若树为空,结束遍历,否则后序遍历左子树,后序遍历右子树,最后访问根节点。
若要是用递归来实现这三种遍历,很简单的,这是先序
void PreOrder1(BTree t)//树的递归实现先序遍历
{
if(t)
{
cout<<(t->data)<<' ';
PreOrder1(t->lchild);
PreOrder1(t->rchild);
}
}
中序和后序只将输出换下位置而已。
说说非递归吧,非递归,,则是要调用栈,先序和中序的非递归每个节点只进栈和出栈一次,而后序则是要进出栈两次,所以后修的非递归实现要使用两个栈,一个用来保存结果,另一个则是辅助栈。(至于为什么后序要进出两次呢?)利用先序非递归方法,对二叉树按照根、右孩子、左孩子的顺序进行访问,访问到节点暂时不输出,而是要保存到另一个栈中,待访问结束后,将被保存的栈中的节点输出即可,所以要用到双栈。
以下是我的运行结果,大家可以先看看,若是觉得有点用处或是有点兴趣,可以选择看一下代码,代码并不高级都是一些基础,本人资历有限,希望这篇文章能够给你一点点的帮助。。。。。。。。。