1. 程式人生 > >二叉樹的相關操作(c語言)

二叉樹的相關操作(c語言)

二叉樹的相關操作:包括先序序列+中序序列建樹丶後序序列+中序序列建樹丶層次序列+中序序列建樹;先序遍歷丶中序遍歷丶後序遍歷丶層次遍歷;二叉樹的深度及最大寬度;度分別為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;

}

 

執行結果