二叉树的相关操作(c语言)

时间:2021-12-29 17:33:10

二叉树的相关操作:包括先序序列+中序序列建树丶后序序列+中序序列建树丶层次序列+中序序列建树;先序遍历丶中序遍历丶后序遍历丶层次遍历;二叉树的深度及最大宽度;度分别为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\n");

    BinaryTreeNode* root1=construct1(preOrder1,midOrder1,8);

 

    //先序遍历树1

       printf("该二叉树的先序遍历为:");

    preOrderRecursion(root1);

    printf("\n");

 

    //中序遍历树1

       printf("该二叉树的中序遍历为:");

    midOrderRecursion(root1);

    printf("\n");

 

    //后序遍历树1

       printf("该二叉树的后序遍历为:");

    postOrderRecursion(root1);

    printf("\n");

 

   //层次遍历树1

       printf("该二叉树的层次遍历为:");

    breadthFirstOrder(root1);

       printf("\n");

 

       //二叉树1的深度

       depth=BiTreeDepth(root1);

       printf("该二叉树的深度为%d\n",depth);

      

 

       //二叉树1的最大宽度

       width=Width(root1);

       printf("该二叉树的最大宽度为%d\n",width);

      

 

       //二叉树1度为0的节点个数

       num0=NodeNumber_0(root1);

       printf("该二叉树度为0的节点个数为%d\n",num0);

 

       //二叉树1度为1的节点个数

       num1=NodeNumber_1(root1);

       printf("该二叉树度为1的节点个数为%d\n",num1);

 

       //二叉树1度为2的节点个数

       num2=NodeNumber_2(root1);

       printf("该二叉树度为2的节点个数为%d\n",num2);

 

       //二叉树1总结点个数

       sum=num0+num1+num2;

       printf("该二叉树度的总节点个数为%d\n",sum);

 

       printf("\n");

        //  后根序列+中根序列建树2

       printf("后根序列+中根序列建树2\n");

       BinaryTreeNode* root2=construct2(postOrder2,midOrder2,7);

        //先序遍历树2

       printf("该二叉树的先序遍历为:");

    preOrderRecursion(root2);

    printf("\n");

 

    //中序遍历树2

       printf("该二叉树的中序遍历为:");

    midOrderRecursion(root2);

    printf("\n");

 

    //后序遍历树2

       printf("该二叉树的后序遍历为:");

    postOrderRecursion(root2);

    printf("\n");

 

   //层次遍历树2

       printf("该二叉树的层次遍历为:");

    breadthFirstOrder(root2);

       printf("\n");

 

       //二叉树2的深度

       depth=BiTreeDepth(root2);

       printf("该二叉树的深度为%d\n",depth);

      

 

       //二叉树2的最大宽度

       width=Width(root2);

       printf("该二叉树的最大宽度为%d\n",width);

      

 

       //二叉树2度为0的节点个数

       num0=NodeNumber_0(root2);

       printf("该二叉树度为0的节点个数为%d\n",num0);

 

       //二叉树2度为1的节点个数

       num1=NodeNumber_1(root2);

       printf("该二叉树度为1的节点个数为%d\n",num1);

 

       //二叉树2度为2的节点个数

       num2=NodeNumber_2(root2);

       printf("该二叉树度为2的节点个数为%d\n",num2);

 

       //二叉树2总结点个数

       sum=num0+num1+num2;

       printf("该二叉树度的总节点个数为%d\n",sum);

       printf("\n");

      

       //层次序列+中根序列建树3

       printf("层次序列+中根序列建树3\n");

       BinaryTreeNode* root3;

       root3=(BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));

       construct3(cengOrder3,midOrder3,root3);

       //先序遍历树3

       printf("该二叉树的先序遍历为:");

    preOrderRecursion(root3);

    printf("\n");

 

    //中序遍历树3

       printf("该二叉树的中序遍历为:");

    midOrderRecursion(root3);

    printf("\n");

 

    //后序遍历树3

       printf("该二叉树的后序遍历为:");

    postOrderRecursion(root3);

    printf("\n");

 

   //层次遍历树3

       printf("该二叉树的层次遍历为:");

    breadthFirstOrder(root3);

       printf("\n");

 

       //二叉树3的深度

       depth=BiTreeDepth(root3);

       printf("该二叉树的深度为%d\n",depth);

      

 

       //二叉树3的最大宽度

       width=Width(root3);

       printf("该二叉树的最大宽度为%d\n",width);

      

 

       //二叉树3度为0的节点个数

       num0=NodeNumber_0(root3);

       printf("该二叉树度为0的节点个数为%d\n",num0);

 

       //二叉树3度为1的节点个数

       num1=NodeNumber_1(root3);

       printf("该二叉树度为1的节点个数为%d\n",num1);

 

       //二叉树3度为2的节点个数

       num2=NodeNumber_2(root3);

       printf("该二叉树度为2的节点个数为%d\n",num2);

 

       //二叉树3总结点个数

       sum=num0+num1+num2;

       printf("该二叉树度的总节点个数为%d\n",sum);

       return 0;

}

 

运行结果

二叉树的相关操作(c语言)

 

 

 二叉树的相关操作(c语言)