您的位置:首页 > 其它

二叉树先序、中序、后序遍历算法的实现

2015-08-11 16:49 531 查看
二叉树每个结点至多只有两颗子树,并且子树有左右之分。二叉树的遍历是二叉树的一项重要操作。二叉树的每一棵子树都还是一棵二叉树,因为此特性在实现二叉树的遍历的时候可以分为递归遍历和非递归遍历。

二叉树的递归遍历的实现:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <stack>
#include <queue>

#define OK 1
#define ERROR 0
#define OVERFLOW 1
using namespace std;
int i=0;

typedef struct BiTNode
{
char data;
struct BiTNode *lchild, *rchild;
}BiTNode,BiTree;

//先序遍历创建树
int CreateBiTree(BiTree *&T)
{
char ch;
ch = getchar();
if( ch == '#')
{
T = NULL;
}
else
{
T = (BiTNode *)malloc(sizeof(BiTNode));
if(!T)
exit(OVERFLOW);
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
return OK;
}

void PreOrderBiTree(BiTree *T)//递归先序遍历
{
if(T != NULL)
{
cout<<T->data;
PreOrderBiTree(T->lchild);
PreOrderBiTree(T->rchild);
}
}

void InOrderBiTree(BiTree *T)//递归中序遍历
{
if(T)
{
InOrderBiTree(T->lchild);
cout<<T->data;
InOrderBiTree(T->rchild);
}
}

void PostOrderBiTree(BiTree *T)//递归后序遍历
{
if(T)
{
PostOrderBiTree(T->lchild);
PostOrderBiTree(T->rchild);
cout<<T->data;
}
}


二叉树非递归遍历的实现:

void PreOrder2(BiTree *T)     //非递归前序遍历
{
stack<BiTree*> s;
BiTree *p = T;
while(p!=NULL||!s.empty())
{
while(p!=NULL)
{
cout<<p->data;
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->rchild;
}
}
}

void InOrder2(BiTree *T)//非递归中序遍历
{
stack<BiTree*> s;
BiTree *p = T;
while(p!=NULL || !s.empty())
{
while(p!=NULL)
{
s.push(p);
p = p->lchild;
}
if(!s.empty())
{
p=s.top();
cout<<p->data;
s.pop();
p = p->rchild;
}
}
}

void PostOrder2(BiTree *T)     //非递归后序遍历
{
stack<BiTree*> s;
BiTree *cur;                      //当前结点
BiTree *pre=NULL;                 //前一次访问的结点
s.push(T);
while(!s.empty())
{
cur=s.top();
if((cur->lchild==NULL&&cur->rchild==NULL)||
(pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
{
cout<<cur->data;  //如果当前结点没有孩子结点或者孩子节点都已被访问过
s.pop();
pre=cur;
}
else
{
if(cur->rchild!=NULL)
s.push(cur->rchild);
if(cur->lchild!=NULL)
s.push(cur->lchild);
}
}
}


层次遍历:即从上到下从左到右依次遍历。层次遍历中需要用到queue进行操作,C++的queue文件中提供了其相关的操作。

void LevelOrder(BiTree *T)//层次遍历
{
queue<BiTree*> q;
BiTree *p = T;
q.push(T);
while(!q.empty())
{
p = q.front();
cout<<p->data;
q.pop();
if(p->lchild)
q.push(p->lchild);
if(p->rchild)
q.push(p->rchild);
}
}


对于二叉树除了比较重要的遍历操作外,统计二叉树叶子结点的个数、求二叉树的深度、宽度、将二叉树的左右子树进行相互交换都是一些重要的操作。

int LeafNumber(BiTree *T)//叶子节点个数
{
if(!T)
return 0;
if(T)
{
if((!T->lchild) && (!T->rchild))
i++;
LeafNumber(T->lchild);
LeafNumber(T->rchild);
}
return i;
}

int maxNumber(int a,int b)
{
if(a>=b)
return a;
else
return b;

}
int GetMaxDepth (BiTree *T)//求树的深度
{

if(!T)
return 0;
else
{
int left=GetMaxDepth(T-&g
4000
t;lchild);
int right= GetMaxDepth(T->rchild);
int num =maxNumber(left,right);
return num+1;
}
}
//树的宽度
//利用层次遍历
//每当一层的节点数入队列时记录增加nextwidth的值,如果其大于width的值,则将其付给width
int GetMaxWidth(BiTree *T)
{
if(!T)
return 0;
queue<BiTree*> qu;
qu.push(T);
int width=1;//最终得到的树的宽度
int curwidth=1;//记录上一层的宽度
int nextwidth=0;
while(!qu.empty())
{
while(curwidth!=0)
{
BiTree* p=qu.front();
qu.pop();
curwidth--;
if(p->lchild!=NULL)
{
qu.push(p->lchild);
nextwidth++;
}
if (p->rchild!=NULL)
{
qu.push(p->rchild);
nextwidth++;
}
}
if(nextwidth>width)
width=nextwidth;
curwidth=nextwidth;
nextwidth=0;
}
return width;
}

BiTree* Change(BiTree *T)//递归式调换左右子树的算法
{
BiTree *p;
if(T==NULL || (T->lchild==NULL && T->rchild==NULL))
return T;
p=T->lchild;
T->lchild = T->rchild;
T->rchild = p;
if(T->lchild)
T->lchild = Change(T->lchild);
if(T->rchild)
T->rchild = Change(T->rchild);
return T;
}

int Change2(BiTree *T)//非递归式交换左右子树
{
stack<BiTree*> s;
BiTree *p;
if(T == NULL)
return 0;
s.push(T);
while (!s.empty())
{
T=s.top();
s.pop();
p = T->lchild;
T->lchild = T->rchild;
T->rchild = p;
if(T->rchild)
s.push(T->rchild);
if(T->lchild)
s.push(T->lchild);
}
return 1;
}


测试程序:

int main()
{
BiTree *T;
cout<<"Enter"<<endl;
CreateBiTree(T);
cout<<"先序递归遍历:";
PreOrderBiTree(T);
cout<<endl<<"先序非递归遍历:";
PreOrder2(T);
cout<<endl<<"中序递归遍历:";
InOrderBiTree(T);
cout<<endl<<"中序非递归遍历:";
InOrder2(T);
cout<<endl<<"后序递归遍历:";
PostOrderBiTree(T);
cout<<endl<<"后序非递归遍历:";
PostOrder2(T);
cout<<endl<<"层次遍历:";
LevelOrder(T);
Change(T);//递归式交换左右子树
cout<<endl<<"交换左右子树后层次遍历:";
LevelOrder(T);
Change2(T);//非递归式交换左右子树
cout<<endl<<"交换左右子树后层次遍历:";
LevelOrder(T);
cout<<endl;
cout<<"二叉树的叶子节点个数是:"<<LeafNumber(T);
cout<<endl<<"二叉树的深度是:"<<GetMaxDepth(T);
cout<<endl<<"二叉树的宽度是:"<<GetMaxWidth(T);
return 0;
}


最后的实验结果:


对程序的输入进行说明:通过先序遍历的方式创建二叉树,#表示其相应的子树为空。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息