二叉树的相关操作:包括先序序列+中序序列建树丶后序序列+中序序列建树丶层次序列+中序序列建树;先序遍历丶中序遍历丶后序遍历丶层次遍历;二叉树的深度及最大宽度;度分别为0,1,2的节点个数以及总结点个数
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
//二叉树节点结构体
struct BinaryTreeNode{
char m_key;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
// 定义栈的存储表示
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
struct SqStack{
char* base;
char* top;
int stacksize;
};
// 定义队列的存储表示
struct QNode {
BinaryTreeNode data; //元素为一棵树
struct QNode* next;
};
struct LinkQueue{
QNode* front;
QNode* rear;
};
// 栈的基本操作的函数
void InitStack(SqStack &S) {
S.base = (char*)malloc(STACK_INIT_SIZE * sizeof(char));
if (!S.base) exit(-1);
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
}
bool StackEmpty(SqStack S) {
if (S.top == S.base) return true;
else return false;
}
void Push(SqStack &S, char e) {
if (S.top - S.base >= S.stacksize) {
S.base = (char*)realloc(S.base,
(S.stacksize + STACKINCREMENT) * sizeof(char));
if (!S.base) exit(-1);
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++ = e;
}
void Pop(SqStack &S, char &e) {
if (S.top == S.base) exit(-1);
e = *--S.top;
}
// 队列的基本操作的函数
void InitQueue(LinkQueue &Q) {
Q.front = Q.rear = (QNode*)malloc(sizeof(QNode));
if (!Q.front) exit(-1);
Q.front->next = NULL;
}
bool QueueEmpty(LinkQueue Q) {
if (Q.front == Q.rear) return true;
else return false;
}
void EnQueue(LinkQueue &Q, BinaryTreeNode e) {
QNode* p;
p = (QNode*)malloc(sizeof(QNode));
if (!p) exit(-1);
p->data = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
}
void DeQueue(LinkQueue &Q, BinaryTreeNode &e) {
if (Q.front == Q.rear) exit(-1);
QNode* p;
p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if (Q.rear == p) Q.rear = Q.front;
free(p);
}
/****************************************
func:根据前序序列和中序序列构建二叉树
para:preOrder:前序序列;midOrder:中序序列;len:节点数
****************************************/
BinaryTreeNode* construct1(char* preOrder,char* midOrder,int len){
if(preOrder==NULL||midOrder==NULL||len<=0)
return NULL;
//先根遍历(前序遍历)的第一个值就是根节点的键值
char rootKey=preOrder[0];
BinaryTreeNode* root=new BinaryTreeNode;
root->m_key=rootKey;
root->m_pLeft=root->m_pRight=NULL;
if(len==1 && *preOrder==*midOrder)//只有一个节点
return root;
//在中根遍历(中序遍历)中找到根节点的值
char* rootMidOrder=midOrder;
int leftLen=0; //左子树节点数
while(*rootMidOrder!=rootKey&&rootMidOrder<=(midOrder+len-1)){
++rootMidOrder;
++leftLen;
}
if(*rootMidOrder!=rootKey)//在中根序列未找到根节点,输入错误
return NULL;
if(leftLen>0){ //构建左子树
root->m_pLeft=construct1(preOrder+1,midOrder,leftLen);
}
if(len-leftLen-1>0){ //构建右子树
root->m_pRight=construct1(preOrder+leftLen+1,rootMidOrder+1,len-leftLen-1);
}
return root;
}
/****************************************
func:根据后序序列和中序序列构建二叉树
para:postOrder:后序序列;midOrder:中序序列;len:节点数
****************************************/
BinaryTreeNode* construct2(char* postOrder,char* midOrder,int len)
{
if(postOrder==NULL || midOrder==NULL || len<=0)
return NULL;
//后根遍历(后序遍历)的最后一个值就是根节点的键值
char rootKey=*(postOrder+len-1); //获取根节点的值
BinaryTreeNode* root=new BinaryTreeNode;
root->m_key=rootKey;
root->m_pLeft=root->m_pRight=NULL;
if(len==1 && *postOrder==*midOrder)//只有一个节点
return root;
//在中根遍历(中序遍历)中找到根节点的值
char* rootMidOrder=midOrder;
int leftLen=0; //左子树节点数
while(*rootMidOrder!=rootKey&&rootMidOrder<=(midOrder+len-1)){
++rootMidOrder;
++leftLen;
}
if(*rootMidOrder!=rootKey)//在中根序列未找到根节点,输入错误
return NULL;
if(leftLen>0){ //构建左子树
root->m_pLeft=construct2(postOrder,midOrder,leftLen);
}
if(len-leftLen-1>0){ //构建右子树
root->m_pRight=construct2(postOrder+leftLen,rootMidOrder+1,len-leftLen-1);
}
return root;
}
/****************************************
func:根据后序序列和层次序列构建二叉树
para:level:层次序列;midOrder:中序序列;root:二叉树指针引用
****************************************/
void construct3(char* level,char* midOrder,BinaryTreeNode* &root)
{
int i;
int len=strlen(level); //取得层次遍历长度
int pos=0;
if(len==0 || level==NULL || midOrder==NULL)
{
return;
}
char *p=strchr(midOrder,level[0]);
if(p==NULL) //如果为空则抛弃第一个,跳到下一个;
{
char *L=(char*)malloc(sizeof(char)*len); //开辟数组
strncpy(L,level+1,len-1); //舍弃第一个
L[len-1]=0;
construct3(L,midOrder,root); //调用建树函数
return ;
}
pos=p-midOrder; //得到中序遍历左子树字符串长度
root->m_key=level[0]; //为根节点赋值
root->m_pLeft=NULL;
root->m_pRight=NULL;
if(pos!=0) //左子树的递归调用
{
root->m_pLeft=(BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
char *left_level=(char*)malloc(sizeof(char)*len);
char *left_inor=(char*)malloc(sizeof(char)*(pos));
strncpy(left_level,level+1,len-1); //舍去层次遍历第一个
strncpy(left_inor,midOrder,pos); //截取左子树字符串
left_level[len-1]=0;
left_inor[pos]=0;
construct3(left_level,left_inor,root->m_pLeft);
}
if(pos < strlen(midOrder)-1) //右子树的递归调用
{
root->m_pRight=(BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
char *right_level=(char*)malloc(sizeof(char)*(len));
char *right_inor=(char*)malloc(sizeof(char)*(len-pos));
strncpy(right_level,level+1,len-1);
strncpy(right_inor,midOrder+pos+1,len-pos-1);
right_level[len-1]=0;
right_inor[len-pos-1]=0;
construct3(right_level,right_inor,root->m_pRight);
}
}
//先根递归遍历
void preOrderRecursion(BinaryTreeNode* root){
if(root==NULL)
return;
printf("%c ",root->m_key);
preOrderRecursion(root->m_pLeft);
preOrderRecursion(root->m_pRight);
}
//中根递归遍历
void midOrderRecursion(BinaryTreeNode* root){
if(root==NULL)
return;
midOrderRecursion(root->m_pLeft);
printf("%c ",root->m_key);
midOrderRecursion(root->m_pRight);
}
//后根递归遍历
void postOrderRecursion(BinaryTreeNode* root){
if(root==NULL)
return;
postOrderRecursion(root->m_pLeft);
postOrderRecursion(root->m_pRight);
printf("%c ",root->m_key);
}
//层次遍历二叉树,使用队列实现
void breadthFirstOrder(BinaryTreeNode* root){
LinkQueue Q;
InitQueue(Q);
BinaryTreeNode p;
if (root)
EnQueue(Q,*root);
else
exit(-1);
while (!QueueEmpty(Q)) {
DeQueue(Q, p);
printf("%c ",p.m_key);
if (p.m_pLeft)
EnQueue(Q,*p.m_pLeft);
if (p.m_pRight)
EnQueue(Q,*p.m_pRight);
}
}
//返回二叉树的深度
int BiTreeDepth( BinaryTreeNode* T)
{
int i,j;
if(!T)
return 0;
if(T->m_pLeft)
i=BiTreeDepth(T->m_pLeft);
else
i=0;
if(T->m_pRight)
j=BiTreeDepth(T->m_pRight);
else
j=0;
return i>j?i+1:j+1;
}
//求二叉树的最大宽度
int LevelWidth(BinaryTreeNode* root,int level)
{
if(!root)return 0;
else
{
if(level==1)
return 1;
level=LevelWidth(root->m_pLeft,level-1)+LevelWidth(root->m_pRight,level-1);
}
return level;
}
int Width(BinaryTreeNode* root)
{
int width,i;
int w[20];
for(i=0;i<20;i++)
w[i]=0;
if(!root)
width=0;
else
{
for(i=0;i<=BiTreeDepth(root);i++)
w[i]=LevelWidth(root,i+1);
}
i=0;
while(w[i])
{
if(w[i]>width)
width=w[i];
i++;
}
return width;
}
//求度为0的节点个数
int NodeNumber_0(BinaryTreeNode* T)
{
int i=0;
if(T)
{
if(T->m_pLeft==NULL && T->m_pRight==NULL)
{
i=1;
}
else
{
i=NodeNumber_0(T->m_pLeft) + NodeNumber_0( T->m_pRight );
}
}
return i;
}
//求度为1的节点个数
int NodeNumber_1(BinaryTreeNode* T)
{
int i=0;
if(T)
{
if( (T->m_pLeft==NULL && T->m_pRight!=NULL) || (T->m_pLeft!=NULL && T->m_pRight==NULL))
{
i=1+NodeNumber_1(T->m_pLeft)+NodeNumber_1(T->m_pRight);
}
else
{
i=NodeNumber_1(T->m_pLeft)+NodeNumber_1(T->m_pRight);
}
}
return i;
}
//求度为2的节点个数
int NodeNumber_2(BinaryTreeNode* T)
{
int i=0;
if(T)
{
if((T->m_pLeft!=NULL)&&(T->m_pRight!=NULL))
{
i=1+NodeNumber_2(T->m_pLeft) + NodeNumber_2(T->m_pRight);
}
else
{
i= NodeNumber_2(T->m_pLeft) + NodeNumber_2(T->m_pRight);
}
}
return i;
}
int main(){
int depth;
int width;
int num0;
int num1;
int num2;
int sum;
//二叉树1先根序列
char preOrder1[9]={'1','2','4','7','3','5','6','8'};
//二叉树1中根序列
char midOrder1[9]={'4','7','2','1','5','3','8','6'};
//二叉树1后根序列
char postOrder1[9]={'7','4','2','5','8','6','3','1'};
//二叉树1层次序列
char cengOrder1[9]={'1','2','3','4','5','6','7','8'};
//二叉树2先根序列
char preOrder2[8]={'A','B','C','D','E','G','F'};
//二叉树2中根序列
char midOrder2[8]={'C','B','E','G','D','F','A'};
//二叉树2后根序列
char postOrder2[8]={'C','G','E','F','D','B','A'};
//二叉树2层次序列
char cengOrder2[8]={'A','B','C','D','E','F','G'};
//二叉树3先根序列
char preOrder3[9]={'H','D','A','C','B','G','F','E'};
//二叉树3中根序列
char midOrder3[9]={'A','D','C','B','H','F','E','G'};
//二叉树3后根序列
char postOrder3[9]={'A','B','C','D','E','F','G','H'};
//二叉树3层次序列
char cengOrder3[9]={'H','D','G','A','C','F','B','E'};
//先根序列+中根序列建树1
printf("先根序列+中根序列建树1 ");
BinaryTreeNode* root1=construct1(preOrder1,midOrder1,8);
//先序遍历树1
printf("该二叉树的先序遍历为:");
preOrderRecursion(root1);
printf(" ");
//中序遍历树1
printf("该二叉树的中序遍历为:");
midOrderRecursion(root1);
printf(" ");
//后序遍历树1
printf("该二叉树的后序遍历为:");
postOrderRecursion(root1);
printf(" ");
//层次遍历树1
printf("该二叉树的层次遍历为:");
breadthFirstOrder(root1);
printf(" ");
//二叉树1的深度
depth=BiTreeDepth(root1);
printf("该二叉树的深度为%d ",depth);
//二叉树1的最大宽度
width=Width(root1);
printf("该二叉树的最大宽度为%d ",width);
//二叉树1度为0的节点个数
num0=NodeNumber_0(root1);
printf("该二叉树度为0的节点个数为%d ",num0);
//二叉树1度为1的节点个数
num1=NodeNumber_1(root1);
printf("该二叉树度为1的节点个数为%d ",num1);
//二叉树1度为2的节点个数
num2=NodeNumber_2(root1);
printf("该二叉树度为2的节点个数为%d ",num2);
//二叉树1总结点个数
sum=num0+num1+num2;
printf("该二叉树度的总节点个数为%d ",sum);
printf(" ");
// 后根序列+中根序列建树2
printf("后根序列+中根序列建树2 ");
BinaryTreeNode* root2=construct2(postOrder2,midOrder2,7);
//先序遍历树2
printf("该二叉树的先序遍历为:");
preOrderRecursion(root2);
printf(" ");
//中序遍历树2
printf("该二叉树的中序遍历为:");
midOrderRecursion(root2);
printf(" ");
//后序遍历树2
printf("该二叉树的后序遍历为:");
postOrderRecursion(root2);
printf(" ");
//层次遍历树2
printf("该二叉树的层次遍历为:");
breadthFirstOrder(root2);
printf(" ");
//二叉树2的深度
depth=BiTreeDepth(root2);
printf("该二叉树的深度为%d ",depth);
//二叉树2的最大宽度
width=Width(root2);
printf("该二叉树的最大宽度为%d ",width);
//二叉树2度为0的节点个数
num0=NodeNumber_0(root2);
printf("该二叉树度为0的节点个数为%d ",num0);
//二叉树2度为1的节点个数
num1=NodeNumber_1(root2);
printf("该二叉树度为1的节点个数为%d ",num1);
//二叉树2度为2的节点个数
num2=NodeNumber_2(root2);
printf("该二叉树度为2的节点个数为%d ",num2);
//二叉树2总结点个数
sum=num0+num1+num2;
printf("该二叉树度的总节点个数为%d ",sum);
printf(" ");
//层次序列+中根序列建树3
printf("层次序列+中根序列建树3 ");
BinaryTreeNode* root3;
root3=(BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
construct3(cengOrder3,midOrder3,root3);
//先序遍历树3
printf("该二叉树的先序遍历为:");
preOrderRecursion(root3);
printf(" ");
//中序遍历树3
printf("该二叉树的中序遍历为:");
midOrderRecursion(root3);
printf(" ");
//后序遍历树3
printf("该二叉树的后序遍历为:");
postOrderRecursion(root3);
printf(" ");
//层次遍历树3
printf("该二叉树的层次遍历为:");
breadthFirstOrder(root3);
printf(" ");
//二叉树3的深度
depth=BiTreeDepth(root3);
printf("该二叉树的深度为%d ",depth);
//二叉树3的最大宽度
width=Width(root3);
printf("该二叉树的最大宽度为%d ",width);
//二叉树3度为0的节点个数
num0=NodeNumber_0(root3);
printf("该二叉树度为0的节点个数为%d ",num0);
//二叉树3度为1的节点个数
num1=NodeNumber_1(root3);
printf("该二叉树度为1的节点个数为%d ",num1);
//二叉树3度为2的节点个数
num2=NodeNumber_2(root3);
printf("该二叉树度为2的节点个数为%d ",num2);
//二叉树3总结点个数
sum=num0+num1+num2;
printf("该二叉树度的总节点个数为%d ",sum);
return 0;
}
运行结果