您的位置:首页 > 其它

二叉树的遍历,深度求解以及竖向打印详析

2014-09-20 14:53 330 查看
二叉树是每个节点最多有两个子树的有序树。二叉树常被用于实现二叉查找树二叉堆。值得注意的是,二叉树不是树的特殊情形。在图论中,二叉树是一个连通的无环图,并且每一个顶点的度不大于2。有根二叉树还要满足根结点的度不大于2。有了根结点后,每个顶点定义了唯一的根结点,和最多2个子结点。然而,没有足够的信息来区分左结点和右结点。二叉树详细请看本文:二叉树

所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问 题。 遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。

代码如下:

#include<iostream>
#include<cstdlib>
using namespace std;
typedef char ElemType;
typedef struct Node
{
ElemType data;
struct Node* LChild;
struct Node* RChild;
}BiTNode,*BiTree;
int LeafCount;
int Depth;

void Visit(ElemType T)//用于遍历的输出
{
cout<<T;
}

//1.建立二叉树
void CreateBiTree(BiTree *bt)
{
char ch;
ch = getchar();
if(ch=='.') *bt=NULL;
else
{
*bt=(BiTree)malloc(sizeof(BiTNode)); //生成一个新结点
(*bt)->data=ch;
CreateBiTree(&((*bt)->LChild)); //生成左子树
CreateBiTree(&((*bt)->RChild)); //生成右子树
}
}

//2.二叉树遍历

void  PreOrder(BiTree root)
/*先序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/
{
if (root!=NULL)
{
Visit(root ->data);  /*访问根结点*/
PreOrder(root ->LChild);  /*先序遍历左子树*/
PreOrder(root ->RChild);  /*先序遍历右子树*/
}
else
cout<<".";
}
void  InOrder(BiTree root)
/*中序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/
{
if (root!=NULL)
{
InOrder(root ->LChild);   /*中序遍历左子树*/
Visit(root ->data);        /*访问根结点*/
InOrder(root ->RChild);   /*中序遍历右子树*/
}
else
cout<<".";
}
void  PostOrder(BiTree root)
/* 后序遍历二叉树,root为指向二叉树(或某一子树)根结点的指针*/
{
if(root!=NULL)
{
PostOrder(root ->LChild); /*后序遍历左子树*/
PostOrder(root ->RChild); /*后序遍历右子树*/
Visit(root ->data);       /*访问根结点*/
}
else
cout<<".";
}

//3.输出二叉树上的“叶子”节点(三种方法,只写了先序,中后请参考前面的2.二叉树遍历)

void  leafPreOrder(BiTree root)
/*先序遍历二叉树, root为指向二叉树根结点的指针*/
{
if (root!=NULL)
{
if (root ->LChild==NULL && root ->RChild==NULL)
Visit(root->data);  /*输出叶子结点*/
PreOrder(root ->LChild);  /*先序遍历左子树*/
PreOrder(root ->RChild);  /*先序遍历右子树*/
}
}

//4.统计叶子节点数目(两个方法)

/* LeafCount保存叶子结点的数目的全局变量,调用之前初始化值为0 */
void leaf_a(BiTree root)//统计叶子节点数目法1
{
if(root!=NULL)
{
leaf_a(root->LChild);
leaf_a(root->RChild);
if (root ->LChild==NULL && root ->RChild==NULL)
LeafCount++;
}
}

int leaf_b(BiTree root)//统计叶子节点数目法2
{
int LeafCount2;
if(root==NULL)
LeafCount2 =0;
else
if((root->LChild==NULL)&&(root->RChild==NULL))
LeafCount2 =1;
else
LeafCount2 =leaf_b(root->LChild)+leaf_b(root->RChild);
/* 叶子数为左右子树的叶子数目之和 */
return LeafCount2;
}

//6.后序遍历求二叉树的高度递归算法

int PostTreeDepth(BiTree bt)
{
int hl,hr,max;
if(bt!=NULL)
{
hl=PostTreeDepth(bt->LChild);  /* 求左子树的深度 */
hr=PostTreeDepth(bt->RChild);  /* 求右子树的深度 */
max=hl>hr?hl:hr;              /* 得到左、右子树深度较大者*/
return(max+1);               /* 返回树的深度 */
}
else return(0);             /* 如果是空树,则返回0 */
}

//6.前序遍历求二叉树的高度递归算法

void PreTreeDepth(BiTree bt, int h)
/* 前序遍历求二叉树bt高度的递归算法,h为bt指向结点所在层次,初值为1*/
/*depth为当前求得的最大层次,为全局变量,调用前初值为0 */
{
if(bt!=NULL)
{
if(h>Depth)
Depth = h;     /*如果该结点层次值大于depth,更新depth的值*/
PreTreeDepth(bt->LChild, h+1);  /* 遍历左子树 */
PreTreeDepth(bt->RChild, h+1);  /* 遍历右子树 */
}
}

//7.“竖向”打印二叉树

void PrintTree(BiTree bt,int nLayer)  /* 按竖向树状打印的二叉树 */
{
if(bt == NULL) return;
PrintTree(bt->RChild,nLayer+1);
for(int i=0;i<nLayer;i++)
printf("  ");
printf("%c\n",bt->data);
PrintTree(bt->LChild,nLayer+1);
}

int main()
{
LeafCount =0;Depth=0;
BiTree T=NULL;
cout<<"请以先序输出的形式输入二叉树构造二叉链表:"<<endl;
CreateBiTree(&T);
cout<<"先序遍历二叉树为:"<<endl;
PreOrder(T);
cout<<endl<<"中序遍历二叉树为:"<<endl;
InOrder(T);
cout<<endl<<"后序遍历二叉树为:"<<endl;
PostOrder(T);
cout<<endl<<"先序输出二叉树叶子节点为:"<<endl;
leafPreOrder(T);
cout<<endl<<"叶子节点数目为:"<<endl;
leaf_a(T);
cout<<endl<<"方法一显示共有"<<LeafCount<<"个叶子节点"<<endl;

cout<<endl<<"方法二显示共有"<<leaf_b(T)<<"个叶子节点"<<endl;

cout<<endl<<"后序遍历求二叉树的高度为"<<PostTreeDepth(T)<<endl;
PreTreeDepth(T,1);
cout<<endl<<"前序遍历求二叉树的高度为"<<Depth<<endl;

cout<<endl<<"竖状打印二叉树为:"<<endl;
PrintTree(T,1);
return 0;
}


附带二叉树遍历的非递归算法:

/* 中后非递归遍历二叉树,作为遍历方法的参考*/

//8.中序遍历二叉树非递归算法(三个)

/*算法a*/
void inorder(BiTree root);
{
int top=0; p=bt;
L1: if (p!=NULL)       /* 遍历左子树 */
{
top=top+2;
if(top>m) return;       /*栈满溢出处理*/
s[top-1]=p;            /* 本层参数进栈 */
s[top]=L2;             /* 返回地址进栈 */
p=p->LChild;           /* 给下层参数赋值 */
goto L1;               /* 转向开始 */
L2:  Visit(p->data);     /* 访问根 */
top=top+2;
if(top>m) return;       /*栈满溢出处理*/;
s[top-1]=p;            /* 遍历右子树 */
s[top]=L3;
p=p->RChild;
goto L1;
}
L3: if(top!=0)
{
addr=s[top];
p=s[top-1];            /* 取出返回地址 */
top=top-2;             /* 退出本层参数 */
goto addr;
}
}

/*算法b*/
void inorder(BiTree root)   /* 中序遍历二叉树,root为二叉树的根结点 */
{
int top=0;
BiTree p;
BiTree s[Stack_Size];
int m;
m = Stack_Size-1;
p = root;
do
{
while(p!=NULL)
{
if (top>m) return;
top=top+1;
s[top]=p;
p=p->LChild;
};  /* 遍历左子树 */
if(top!=0)
{
p=s[top];
top=top-1;
Visit(p->data);  /* 访问根结点 */
p=p->RChild;  /* 遍历右子树 */
}
}
while(p!=NULL || top!=0);
}

/*算法c*/
void  InOrder(BiTree root) /* 中序遍历二叉树的非递归算法 */
{
SeqStack S;
BiTree p;
InitStack (&S);
p=root;
while(p!=NULL || !IsEmpty(&S))
{
if (p!=NULL)  /* 根指针进栈,遍历左子树 */
{
Push(&S,p);
p=p->LChild;
}
else
{  /*根指针退栈,访问根结点,遍历右子树*/
Pop(&S,&p);
Visit(p->data);
p=p->RChild;
}
}
}

//9.后序遍历二叉树的非递归算法

void PostOrder(BiTree root)
{
BiTNode *p,*q;
BiTNode **s;
int top=0;
q=NULL;
p=root;
s=(BiTNode**)malloc(sizeof(BiTNode*)*NUM);
/* NUM为预定义的常数 */
while(p!=NULL || top!=0)
{
while(p!=NULL)
{
top++;
s[top]=p;
p=p->LChild;
}  /*遍历左子树*/
if(top>0)
{
p=s[top];
if((p->RChild==NULL) ||(p->RChild==q))	/* 无右孩子,或右孩子已遍历过 */
{
visit(p->data);        /* 访问根结点*/
q=p;            	/* 保存到q,为下一次已处理结点前驱 */
top--;
p=NULL;
}
else
p=p->RChild;
}
}
free(s);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐