一、二叉树的链式存储:
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;//结点数据
BinTree Left;//指向左子树
BinTree Right;//指向右子树
};
二、遍历(先序,中序、后序、层序)
先序遍历(递归):
对结点的访问是在其左、右子树遍历之前进行的
过程:
1.访问根节点
2.先序遍历其左子树
3.先序遍历其右子树
void PreorderTraversal(BinTree BT)
{
if(BT){
printf("%d ",BT->Data );
PreorderTraversal(BT->Left );
PreorderTraversal(BT->Right );
}
}
中序遍历(递归):
对树中的任一结点的访问是在遍历其左子树后进行的,访问该结点后,在遍历其右子树
过程:
1.中序遍历其左子树
2. 访问根节点
3.中序遍历其右子树
void InorderTraversal(BinTree BT)
{
if(BT){
InorderTraversal(BT->Left );
printf("%d ",BT->Data );//数据类型根据要求变化
InorderTraversal(BT->Right );
}
}
中序遍历(非递归):
void InorderTraversal(BinTree BT)
{
BinTree T;
Stack S=CreateStack();//创建空堆栈
T=BT;//从根节点出发
while(T||!IsEmpty(S)){
while(T){
//一直向左并将沿途结点压入堆栈
Push(S,T);
T=T->Left ;
}
T=Pop(S);//弹出堆栈
printf("%d",T->Data );//打印结点
T=T->Right ; //转向右子树
}
}
后序遍历(递归):
结点左右子树的遍历先进行,然后访问该结点
过程:
1.后序遍历其左子树
2.后序遍历其右子树
3. 访问根结点
void PostorderTraversal (BinTree BT)
{
if(BT){
PostorderTraversal(BT->Left );
PostorderTraversal(BT->Right );
printf("%d ",BT->Data );
}
}
层序遍历(非递归):
按树的层次遍历
过程:
1.从队列中取出一个元素
2.访问该元素所指结点
3.若该元素所指的左、右孩子非空,则将其左、右孩子的指针顺序入队
void LevelorderTraversal(BinTree BT)
{
Queue Q;
BinTree T;
if(!BT)return ;//若是空树,直接返回
Q=CreateQueue(5);//创建空队列
AddQ(Q,BT);
while(!IsEmpty(Q)){
T=DeleteQ(Q);
printf("%d",T->Data );//访问结点
if(T->Left )AddQ(Q,T->Left );
if(T->Right)AddQ(Q,T->Right );
}
}
三、求二叉树的高度:
int GetHeight(BinTree BT)
{
int HL,HR,MaxH;
if(BT){
HL=GetHeight(BT->Left );//左子树的高度
HR=GetHeight(BT->Right );//右子树的高度
MaxH = HL>HR ? HL : HR;
return (MaxH+1);//返回树的高度
}
else return 0;//空树高度为0
}
四、二叉树的创建(层序创建):
使用队列暂时存储各结点的地址 (空结点的数值为0)
过程:
1.输入第一个数据:
若为0,表示此树为空,将空指针赋给根指针,树构造完毕
若不为空,动态分配一个结点单元,并存入数据,同时将该结点地址放入队列
2.若队列不为空,从队列中取出一个结点地址,并建立该结点的左右孩子
从输入序列中读入下一个数据
若读入的数据为0,将出队结点的左孩子指针置空
读入的数据不为0,分配一个结点单元,存入所读数值,并将其置为出队结点的左孩子,将此孩子地址入队
接着从序列中读入下一个数据
若读入的数据为0,将出队结点的右孩子指针置空
读入的数据不为0,分配一个结点单元,存入所读数值,并将其置为出队结点的右孩子,将此孩子地址入队
3. 重复2的过程,直到队列为空,再无结点出队,构造过程结束
BinTree CreateBinTree()
{
ElementType Data;
BinTree BT,T;
Queue Q=CreateQueue(5);//创建空队列
printf("请输入根结点数据:");
scanf("%d",&Data);//建立根结点
if(Data!=NoInfo){
//分配根结点单元,并将结点地址入队
BT=(BinTree)malloc(sizeof(struct TNode));
BT->Data =Data;
BT->Left =BT->Right =NULL;
AddQ(Q,BT);
}
else return NULL;//空树
printf("请输入结点数据:");
while(!IsEmpty(Q)){
T=DeleteQ(Q);//从队列中取出一个结点地址
scanf("%d",&Data);//读入T的左孩子
if(Data==NoInfo)T->Left=NULL;//左孩子为空
else{
T->Left =(BinTree)malloc(sizeof(struct TNode));
T->Left->Data =Data;
T->Left->Left =T->Left->Right =NULL;
AddQ(Q,T->Left );
}
scanf("%d",&Data);
if(Data==NoInfo)T->Right=NULL;//右孩子为空
else{
T->Right =(BinTree)malloc(sizeof(struct TNode));
T->Right->Data =Data;
T->Right->Left =T->Right->Right =NULL;
AddQ(Q,T->Right );
}
} //结束while循环
return BT;
}
五、完整代码:
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define ERROR -1//ERROR为队列不可能取到的值
#define NoInfo 0//空结点数值
typedef int ElementType;
//二叉树的链式存储
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;//结点数据
BinTree Left;//指向左子树
BinTree Right;//指向右子树
};
//队列的顺序存储
typedef struct QNode *PtrToQNode;
struct QNode{
BinTree *Data;//存储元素的数组
ElementType Front,Rear;//队列的头、尾
int MaxSize;//队列最大容量
};
typedef PtrToQNode Queue;
//1.创建
Queue CreateQueue(int MaxSize)
{
Queue Q=(Queue)malloc(sizeof(struct QNode));
Q->Data =(BinTree *)malloc(MaxSize*sizeof(BinTree));
Q->Front =Q->Rear =0;
Q->MaxSize =MaxSize;
return Q;
}
//2.插入
bool IsFull(Queue Q)
{
return ((Q->Rear +1 )%Q->MaxSize ==Q->Front );
}
void AddQ(Queue Q,BinTree BT)
{
Q->Rear =(Q->Rear +1)%Q->MaxSize ;//队尾向后移一个位置
Q->Data [Q->Rear ]=BT;
}
//3.删除
bool IsEmpty(Queue Q)
{
return (Q->Front ==Q->Rear);
}
BinTree DeleteQ(Queue Q)
{
Q->Front =(Q->Front +1)%Q->MaxSize ;//头向后移一个位置
return Q->Data [Q->Front ];
}
//中序遍历
void InorderTraversal(BinTree BT)
{
if(BT){
InorderTraversal(BT->Left );
printf("%d ",BT->Data );//数据类型根据要求变化
InorderTraversal(BT->Right );
}
}
//先序遍历
void PreorderTraversal(BinTree BT)
{
if(BT){
printf("%d ",BT->Data );
PreorderTraversal(BT->Left );
PreorderTraversal(BT->Right );
}
}
//后序遍历
void PostorderTraversal (BinTree BT)
{
if(BT){
PostorderTraversal(BT->Left );
PostorderTraversal(BT->Right );
printf("%d ",BT->Data );
}
}
//---------非递归算法--------------
//中序遍历
//void InorderTraversal(BinTree BT)
//{
// BinTree T;
// Stack S=CreateStack();//创建空堆栈
// T=BT;//从根节点出发
// while(T||!IsEmpty(S)){
// while(T){
// //一直向左并将沿途结点压入堆栈
// Push(S,T);
// T=T->Left ;
// }
// T=Pop(S);//弹出堆栈
// printf("%d",T->Data );//打印结点
// T=T->Right ; //转向右子树
// }
//}
//层序遍历
//void LevelorderTraversal(BinTree BT)
//{
// Queue Q;
// BinTree T;
// if(!BT)return ;//若是空树,直接返回
// Q=CreateQueue(5);//创建空队列
// AddQ(Q,BT);
// while(!IsEmpty(Q)){
// T=DeleteQ(Q);
// printf("%d",T->Data );//访问结点
// if(T->Left )AddQ(Q,T->Left );
// if(T->Right)AddQ(Q,T->Right );
// }
// }
//求二叉树的高度
int GetHeight(BinTree BT)
{
int HL,HR,MaxH;
if(BT){
HL=GetHeight(BT->Left );//左子树的高度
HR=GetHeight(BT->Right );//右子树的高度
MaxH = HL>HR ? HL : HR;
return (MaxH+1);//返回树的高度
}
else return 0;//空树高度为0
}
/*-----------二叉树的创建-------------*/
BinTree CreateBinTree()
{
ElementType Data;
BinTree BT,T;
Queue Q=CreateQueue(5);//创建空队列
printf("请输入根结点数据:");
scanf("%d",&Data);//建立根结点
if(Data!=NoInfo){
//分配根结点单元,并将结点地址入队
BT=(BinTree)malloc(sizeof(struct TNode));
BT->Data =Data;
BT->Left =BT->Right =NULL;
AddQ(Q,BT);
}
else return NULL;//空树
printf("请输入结点数据:");
while(!IsEmpty(Q)){
T=DeleteQ(Q);//从队列中取出一个结点地址
scanf("%d",&Data);//读入T的左孩子
if(Data==NoInfo)T->Left=NULL;//左孩子为空
else{
T->Left =(BinTree)malloc(sizeof(struct TNode));
T->Left->Data =Data;
T->Left->Left =T->Left->Right =NULL;
AddQ(Q,T->Left );
}
scanf("%d",&Data);
if(Data==NoInfo)T->Right=NULL;//右孩子为空
else{
T->Right =(BinTree)malloc(sizeof(struct TNode));
T->Right->Data =Data;
T->Right->Left =T->Right->Right =NULL;
AddQ(Q,T->Right );
}
} //结束while循环
return BT;
}
int main()
{
BinTree BT;
BT=CreateBinTree();
int height=GetHeight(BT);
printf("二叉树的高度为:%d\n",height);
printf("先序遍历结果:");
PreorderTraversal(BT);
printf("\n");
printf("中序遍历结果:");
InorderTraversal(BT);
printf("\n");
printf("后序遍历结果:");
PostorderTraversal(BT);
printf("\n");
return 0;
}
运行:
![](https://i-blog.csdnimg.cn/blog_migrate/f5456a15f90be0358b5f40d7bb83e6cc.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4ddd03af5d55d052a462afbe3c7013d3.png)