二叉树是每个节点最多有两个子树的有序树。二叉树常被用于实现二叉查找树和二叉堆。值得注意的是,二叉树不是树的特殊情形。在图论中,二叉树是一个连通的无环图,并且每一个顶点的度不大于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);
}