二叉树遍历就是如何按某条搜索路径巡访树中的每个结点,使得每个结点均被访问依次,而且仅被访问一次。
函数定义:
/*创建空二叉树*/
InitBiTree(T)
/*二叉树的创建*/
CreateBiTree(T)
/*先序遍历二叉树*/
PreOrderTraverse(T)
/*中序遍历二叉树*/
InOrderTraverse(T)
/*后续遍历二叉树*/
PostOrderTraverse(T)
/*求二叉树的高度*/
High(T)
/*求二叉树的结点数目*/
Count(T)
/*实现左右子树交换*/
exchange(T)
三种不同遍历的定义:
先序遍历
1)访问根
2)先序遍历左子树
3)先序遍历右子树
/*先序遍历二叉树*/
void PreOrderTraverse(BiTNode *p)
{
if(p!=NULL)
{
printf("%d ",p->data);
PreOrderTraverse(p->lchild);
PreOrderTraverse(p->rchild);
}
}
/*前序非递归遍历二叉树:栈*/
Status PreOrderTraverse(BiTree T)
{
stack S;
InitStack(S);
BiTree p=T; //p指向当前访问的结点
while(p||!StackEmpty(S))
{
if(p)
{
printf("%c",p->data);
Push(S,p);
p=p->lchild;
}else{
Pop(S,p);
p=p->rchild;
}
}
return OK;
}
中序遍历
1)中序遍历左子树
2)访问根结点
3)最后中序遍历右子树
/*中序遍历二叉树*/
void InOrderTraverse(BiTNode *p)
{
if(p!=NULL)
{
PreOrderTraverse(p->lchild);
printf("%d ",p->data);
PreOrderTraverse(p->rchild);
}
}
中序非递归遍历二叉树
/*中序非递归遍历二叉树:栈*/
Status InOrderTraverse(BiTree T)
{
stack S;
BiTree p;
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);
printf("%d",p->data); //当前根结点
Push(S,p->rchild);
}
}
return OK;
}
/*中序非递归遍历二叉树:栈*/
Status InOrderTraverse(BiTree T)
{
stack S;
InitStack(S);
BiTree p=T;
while(p||!StackEmpty(S))
{
if(p)
{ //非空指针进栈,继续左进
Push(S,p);
p=p->lchild;
}else{ //上层指针退栈,访问其所指结点,再向右进
Pop(S,p);
printf("%d",p->data);
p=p->child;
}
}
return OK;
}
后序遍历
1)首先后序遍历左子树
2)再后序遍历右子树
3)最后访问根
/*后续遍历二叉树*/
void PostOrderTraverse(BiTNode *p)
{
if(p!=NULL)
{
PostOrderTraverse(p->lchild);
PostOrderTraverse(p->rchild);
printf("%d ",p->data);
}
}
后续遍历二叉树:
/*后序非递归遍历二叉树:栈*/
Status PostOrderTraverse(BiTree T)
{
stack S;
InitStack(S);
BiTree p=T;
pre=NULL;
while(p||!StackEmpty(S))
{
if(p){
Push(S,p);
p=p->left;
}else{
Pop(S,p);
if(p->right!=NULL&&pre!=p->right)
{//pre指向上次访问的右结点,避免再次访问
p=p->right;
}else{
printf("%d",p->data);
pre=p;
p=NULL;
}
}
}
}
/*后序非递归遍历二叉树:栈*/
Status PostOrderTraverse(BiTree T)
{
BiTree p = T,last = NULL;
stack S;
InitStack(S);
Push(S,p);
while(!StackEmpty(S))
{
Pop(S,p);
if(last == p->left || last == p->right)//左右子树已经访问完了,该访问根节点了
{
printf("%d",p->data);
last = p;
}
else if(p->left || p->right) //左右子树未访问,当前节点入栈,左右节点入栈
{
Push(S,p);
if(p->right)
Push(S,p->right);
if(p->left)
Push(S,p->left);
}
else //当前节点为叶节点,访问
{
printf("%d",p->data);
last = p;
}
}
}
层次遍历二叉树
/*按照层次遍历二叉树*/
void LevelOrderTraverse(BiTree T)
{
Queue BiNodeQueue;
BiTree p=T;
EnQueue(BiNodeQueue,p);
while(!BiNodeQueue.Empty())
{
DeQueue(BiNodeQueue,p);
if(p)
{
printf("%c",p->data);
EnQueue(BiNodeQueue,p->lchild);
EnQueue(BiNodeQueue,p->rchild);
}
}
}
下面还给了求二叉树结点个数、寻找树的高度和左右子树互换实现:
/*求二叉树的结点数目*/
Status Count(BiTree T)
{
if(T==NULL)
{
return 0;
}
return Count(T->lchild)+Count(T->rchild)+1;
}
/*求二叉树的高度*/
Status High(BiTNode *p)
{
int lh=0;
int rh=0;
if(p==NULL)
{
return 0;
}
lh=High(p->lchild);
rh=High(p->rchild);
if(lh>rh) //求二叉树的遍历左右子树返回最大的那一个值
{
return lh+1;
}
else
{
return rh+1;
}
}
/*实现左右子树交换*/
Status exchange(BiTree T)
{
if(T==NULL){
return 0;
}else{
BiTree temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
exchange(T->lchild);
exchange(T->rchild);
}
}
嗯下面就是在VC中的测试:
#include<stdio.h>
#include<stdlib.h>
#define ERROR 0
#define OK 1
typedef int Status;
typedef int ElemType;
typedef struct BiTNode
{
ElemType data;
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode,*BiTree;
/*创建空二叉树*/
Status InitBiTree(BiTree &T)
{
T=NULL;
return OK;
}
/*二叉树的创建*/
Status CreateBiTree(BiTree &T)
{
int ch;
printf("请输入存放到树中的数据元素:");
scanf("%d",&ch);
if(ch==-1){ //截止二叉树的创建
T=NULL;
return ERROR;
}else{
T=(BiTNode*)malloc(sizeof(BiTNode));//申请结点空间
if(!T)
{
printf("二叉树创建失败!\n");
return ERROR;
}else{
printf("%d成功放入树中\n",ch);
T->data=ch;
CreateBiTree(T->lchild); //构造左子树
CreateBiTree(T->rchild); //构造右子树
return OK;
}
}
}
/*先序遍历二叉树*/
void PreOrderTraverse(BiTNode *p)
{
if(p!=NULL)
{
printf("%d ",p->data);
PreOrderTraverse(p->lchild);
PreOrderTraverse(p->rchild);
}
}
/*中序遍历二叉树*/
void InOrderTraverse(BiTNode *p)
{
if(p!=NULL)
{
PreOrderTraverse(p->lchild);
printf("%d ",p->data);
PreOrderTraverse(p->rchild);
}
}
/*后续遍历二叉树*/
void PostOrderTraverse(BiTNode *p)
{
if(p!=NULL)
{
PostOrderTraverse(p->lchild);
PostOrderTraverse(p->rchild);
printf("%d ",p->data);
}
}
/*求二叉树的高度*/
Status High(BiTNode *p)
{
int lh=0;
int rh=0;
if(p==NULL)
{
return 0;
}
lh=High(p->lchild);
rh=High(p->rchild);
if(lh>rh) //求二叉树的遍历左右子树返回最大的那一个值
{
return lh+1;
}
else
{
return rh+1;
}
}
/*求二叉树的结点数目*/
Status Count(BiTree T)
{
if(T==NULL)
{
return 0;
}
return Count(T->lchild)+Count(T->rchild)+1;
}
/*实现左右子树交换*/
Status exchange(BiTree T)
{
if(T==NULL){
return 0;
}else{
BiTree temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
exchange(T->lchild);
exchange(T->rchild);
}
}
int main()
{
int ch;
BiTree T;
CreateBiTree(T);
printf("**********************************\n");
printf("1、先序遍历二叉树\n2、中序遍历二叉树\n3、后序遍历二叉树\n");
printf("4、输出二叉树高度\n5、输出结点的数目\n6、左右的子树交换\n");
printf("输入0退出操作\n");
printf("**********************************\n");
printf("请输入要进行的操作:");
while(scanf("%d",&ch)&&ch!=0)
{
if(ch==1){
PreOrderTraverse(T);
printf("\n");
}
if(ch==2){
InOrderTraverse(T);
printf("\n");
}
if(ch==3){
PostOrderTraverse(T);
printf("\n");
}
if(ch==4){
printf("二叉树的高度为%d\n",High(T));
}
if(ch==5){
printf("二叉树的结点数目为%d\n",Count(T));
}
if(ch==6){
exchange(T);
printf("二插树左右子树成功交换\n");
}
printf("请输入要进行的操作:");
}
return 0;
}