1. 二叉树的定义
二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。
2. 二叉树的存储结构
#define TRUE 1 //函数的结构的结果状态
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define INFEASIBLE -2
#define Max_Tree_SIZE 20 //最大结点数
typedef int Status;
typedef char TElemType;
typedef struct BiTNode
{
TElemType data,n;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef BiTree SElemType;
typedef BiTree QElemType;
3. 初始化一个二叉树
Status InitBiTree(BiTree *BT) /*构造二叉树*/
{
*BT = NULL;
return TRUE;
}
4. 建立二叉树
通过后序递归建立二叉树,因为后序相对于其他来说比较方便一点。
Status CreateBiTree(BiTree *BT) /*后序递归建立二叉树*/
{
char ch;
scanf_s("%c",&ch);
if(ch=='#')
*BT=NULL;
else{
*BT=(BiTree)malloc(sizeof(BiTNode));
CreateBiTree(&(*BT)->lchild);
CreateBiTree(&(*BT)->rchild);
(*BT)->data=ch;
}
return OK;
}
5 遍历二叉树
5.1 先序遍历二叉树
Status PreOrder(BiTree BT) /*先序递归遍历*/
{
if(BT!=NULL){
if( !(BT->data))
return ERROR;
printf("%c ",BT->data);
PreOrder(BT->lchild);
PreOrder(BT->rchild);
return OK;
}
return OK;
}
运用上图先序遍历结果为: 1 2 4 3 5 6
记住口诀:中左右。中代码结点,左代表左子树,右代表右子树。
5.2 中序遍历二叉树
Status InOrder(BiTree BT) /*中序递归遍历*/
{
if(BT!=NULL)
{
InOrder( BT->lchild);
printf("%c ",BT->data );
BT->n++;
InOrder( BT->rchild);
return OK;
}
return OK;
}
遍历结果为: 4 2 1 5 6 3
记住口诀:左中右。中代码结点,左代表左子树,右代表右子树。
5.3 后序遍历二叉树
Status PostOrder(BiTree BT) /*后序递归遍历*/
{
if(BT!=NULL)
{
PostOrder( BT->lchild);
PostOrder( BT->rchild);
printf("%c ",BT->data );
return OK;
}
return OK;
}
遍历结果为: 4 2 6 5 3 1
记住口诀:左右中。中代码结点,左代表左子树,右代表右子树。
5.4 按层次非递归遍历二叉树
Status LevelOrder(BiTree BT) /*按层次非递归遍历*/
{
for(int i=1;i<BT->n;i++)
if(BT->data!='#')
printf("%c",BT->data);
return OK;
}
遍历结果为: 1 2 3 4 5 6
在定义二叉树数据结构时候,在每个数当中设置了顺序,所以能直接遍历求得层次遍历。
5.5 先序非递归递归遍历二叉树
Status NRPreOrder(BiTree BT) /*先序非递归递归遍历*/
{
BiTree stack[Max_Tree_SIZE],p;
int top;
if(BT==NULL)
return FALSE;
top=0;
p=BT;
while(!(p==NULL&&top==0))
{
while (p!=NULL)
{
printf("%c",p->data);
if(top<Max_Tree_SIZE-1)
{
stack[top]=p;
top++;
}
else
{
printf("溢出");
return 0;
}
p=p->lchild;
}
if(top<=0)
return 0;
else
{
top--;
p=stack[top];
}
p=p->rchild;
}
return OK;
}
第一步:将结点数据输出,将其压入栈中,如果存在左孩子,就让结点指向左孩子,并且继续输出结点和压入栈中,直到不存在左孩子,才停止。
第二步:然后把结点出栈,并且每次指向右孩子,如果右孩子为空,则继续出栈;如果不为空,则输出右孩子结点数据,并且压入栈中执行1.
最后一直重复上述过程,直到结点为空且栈为空时候结束。
6 二叉树其他应用
6.1 求二叉树高度
int max(int a,int b)
{
if(a>b)
return a;
else
return b;
}
int TreeDepth(BiTree BT) /*求高度*/
{
if(BT==NULL)
return 0;
else
return max(TreeDepth(BT->lchild),TreeDepth(BT->rchild))+1;
}
左右递归查出深度最大的子树,就你得出二叉树的高度。
6.2 求二叉树叶子结点数
int LeafNumber(BiTree BT,int &count) /*求叶结点数*/
{
if(BT){
LeafNumber(BT->lchild,count);
if( (!BT->lchild && !BT->rchild))
count++;
LeafNumber(BT->rchild,count);
return 0;
}
return OK;
}
左右递归,找出不存在左子树和右子树的结点,然后加一。
6.3 交换二叉树左右结点位置
void change_left_right(BiTree BT)
{
BiTree p;
p=(BiTree)malloc(sizeof(BiTNode));
if(BT)
{
change_left_right(BT->lchild);
change_left_right(BT->rchild);
p=BT->lchild;
BT->lchild=BT->rchild;
BT->rchild=p;
}
}
左右递归,如果存在结点不为叶子结点,就将其左右子树进行交互,这里要先建立一个中间变量才能进行交换。
7. 全部代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
#define TRUE 1 //函数的结构的结果状态
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define INFEASIBLE -2
#define Max_Tree_SIZE 20 //最大结点数
typedef int Status;
typedef char TElemType;
typedef struct BiTNode
{
TElemType data,n;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef BiTree SElemType;
typedef BiTree QElemType;
Status InitBiTree(BiTree *BT) /*构造二叉树*/
{
*BT = NULL;
return TRUE;
}
Status CreateBiTree(BiTree *BT) /*后序递归建立二叉树*/
{
char ch;
scanf_s("%c",&ch);
if(ch=='#')
*BT=NULL;
else{
*BT=(BiTree)malloc(sizeof(BiTNode));
CreateBiTree(&(*BT)->lchild);
CreateBiTree(&(*BT)->rchild);
(*BT)->data=ch;
}
return OK;
}
Status PreOrder(BiTree BT) /*先序递归遍历*/
{
if(BT!=NULL){
if( !(BT->data))
return ERROR;
printf("%c ",BT->data);
PreOrder(BT->lchild);
PreOrder(BT->rchild);
return OK;
}
return OK;
}
Status InOrder(BiTree BT) /*中序递归遍历*/
{
if(BT!=NULL)
{
InOrder( BT->lchild);
printf("%c ",BT->data );
BT->n++;
InOrder( BT->rchild);
return OK;
}
return OK;
}
Status PostOrder(BiTree BT) /*后序递归遍历*/
{
if(BT!=NULL)
{
PostOrder( BT->lchild);
PostOrder( BT->rchild);
printf("%c ",BT->data );
return OK;
}
return OK;
}
Status LevelOrder(BiTree BT) /*按层次非递归遍历*/
{
for(int i=1;i<BT->n;i++)
if(BT->data!='#')
printf("%c",BT->data);
return OK;
}
Status NRPreOrder(BiTree BT) /*先序非递归递归遍历*/
{
BiTree stack[Max_Tree_SIZE],p;
int top;
if(BT==NULL)
return FALSE;
top=0;
p=BT;
while(!(p==NULL&&top==0))
{
while (p!=NULL)
{
printf("%c",p->data);
if(top<Max_Tree_SIZE-1)
{
stack[top]=p;
top++;
}
else
{
printf("溢出");
return 0;
}
p=p->lchild;
}
if(top<=0)
return 0;
else
{
top--;
p=stack[top];
}
p=p->rchild;
}
return OK;
}
int max(int a,int b)
{
if(a>b)
return a;
else
return b;
}
int TreeDepth(BiTree BT) /*求高度*/
{
if(BT==NULL)
return 0;
else
return max(TreeDepth(BT->lchild),TreeDepth(BT->rchild))+1;
}
int LeafNumber(BiTree BT,int &count) /*求叶结点数*/
{
if(BT){
LeafNumber(BT->lchild,count);
if( (!BT->lchild && !BT->rchild))
count++;
LeafNumber(BT->rchild,count);
return 0;
}
return OK;
}
void change_left_right(BiTree BT)
{
BiTree p;
p=(BiTree)malloc(sizeof(BiTNode));
if(BT)
{
change_left_right(BT->lchild);
change_left_right(BT->rchild);
p=BT->lchild;
BT->lchild=BT->rchild;
BT->rchild=p;
}
}
int main(){
BiTree BT;
// TElemType ch;
BT = (BiTree)malloc(sizeof(BiTNode));
int flag=1,select,count=0;
printf("\n");
printf("To Creat Binary Tree , Please Input PreOrder with ‘#’:");/*输入二叉树的先序序列,用#代表空结点*/
InitBiTree(&BT);
CreateBiTree(&BT); //创建二叉树,返回根节点BT*/
// PreOrder(BT);
printf("\n");
// InOrder(BT);
printf("\n");
// PostOrder(BT);
while(flag){
printf("Please select:\n");
printf("1. PreOrder Traversal \n");
printf("2. InOrder Traversal \n");
printf("3. PostOrder Traversal \n");
printf("4. LevelOrder Traversal \n");
printf("5. NRPreOrder Traversal \n");
printf("6. NRPreOrder Traversal \n");
scanf_s("%d",&select);
switch(select){
case 1: printf("\n The PreOrder Traversal of Binary Tree is:");
PreOrder(BT); //先序递归遍历
break;
case 2: printf("\n The InOrder Traversal of Binary Tree is:");
InOrder(BT); //中序递归遍历
break;
case 3: printf("\n The PostOrder Traversal of Binary Tree is:");
PostOrder(BT); //后序递归遍历
break;
case 4: printf("\n The LevelOrder Traversal of Binary Tree is:");
LevelOrder(BT); //按层次非递归遍历
break;
case 5: printf("\n The NRPreOrder Traversal of Binary Tree is:");
NRPreOrder(BT); //先序非递归递归遍历
break;
case 6: printf("\n The Depth of Binary Tree is:%d",TreeDepth(BT));
//求高度
break;
case 7: LeafNumber(BT,count);//求叶结点数
printf("\n The Number of leaf is:%d",count);
break;
case 8: change_left_right(BT);
break;
}
printf("\n");
}
getchar();
getchar();
return 0;
}