1. 程式人生 > >求二叉樹的深度、寬度和葉子結點數

求二叉樹的深度、寬度和葉子結點數

  如果用連結串列來儲存二叉樹,那麼可以將二叉樹定義如下: 

typedef char ElemType;
typedef struct node{
    ElemType data;     //資料元素
    struct node* lchild;  //指向左孩子
    struct node* rchild;  //指向右孩子
}BTNode;

問題一:二叉樹的深度
  二叉樹的深度,也叫二叉樹的高度,二叉樹的深度等於從根結點到葉子結點的最長路徑加1。用遞迴的觀點來看,二叉樹的深度,等於其最大左右子樹的深度加1,而每個左子樹(右子樹)又可以分解為次左子樹+次右子樹,它們是深度也是最大子樹深度加1。也就是二叉樹深度的遞迴模型f(b)如下:  {

f(b)=0,f(b)=Max{f(b>lchid),f(b>rchild)}+1,b=NULL

對應的遞迴演算法如下:

//求二叉樹b的深度
int BTNodeDepth(BTNode *b){
    int lchilddep,rchilddep;
    if(b==NULL)
        return 0;
    else{
        lchilddep=BTNodeDepth(b->lchild);
        rchilddep=BTNodeDepth(b->rchild);
        return (lchilddep>rchilddep)?(lchilddep+1
):(rchilddep+1); } }

問題二:二叉樹的寬度
  二叉樹的寬度:具有結點數最多的那一層的結點個數。
  採用分層遍歷的方法求出所有結點的層編號,然後,求出各層的結點總數,通過比較找出層結點數最多的值。對應的演算法如下:  

//求二叉樹b的寬度
int BTWidth(BTNode *b){
    struct{
        int lno;        //結點的層次編號
        BTNode *p;      //結點指標
    }Qu[MaxSize];      //定義順序非迴圈佇列
    int front,rear;
    int lnum,max
,i,n; front=rear=0; //置佇列為空 if (b!=NULL) { rear++; Qu[rear].p=b; //根結點指標入隊 Qu[rear].lno=1; //根結點的層次編號為1 while (rear!=front) //佇列不為空 { front++; b=Qu[front].p; //隊頭出隊 lnum=Qu[front].lno; if (b->lchild!=NULL) //左孩子入隊 { rear++; Qu[rear].p=b->lchild; Qu[rear].lno=lnum+1; } if (b->rchild!=NULL) //右孩子入隊 { rear++; Qu[rear].p=b->rchild; Qu[rear].lno=lnum+1; } } max=0; lnum=1; i=1; while (i<=rear) { n=0; while (i<=rear && Qu[i].lno==lnum) { n++; i++; } lnum=Qu[i].lno; if(n>max) max=n; } return max; } else return 0; }

問題三:二叉樹b的葉子結點個數
  當b為空樹時,葉子結點數為0;
  當b的左子樹和右子樹都為空,b只有一個結點時,葉子結點數為1;
  當b的左子樹或右子樹不為空時,葉子結點數=左子樹葉子結點數+右子樹葉子結點數。
  即遞迴模型為:

f(b)=0,f(b)=1,f(b)=f(b>lchild)+f(b>rchild),b=NULLb->lchild==NULLb->rchild==NULL

對應的遞迴演算法如下:

//求二叉樹b的葉子結點個數
int LeafNodes(BTNode *b){
    int num1,num2;
    if(b==NULL)
        return 0;
    else if(b->lchild==NULL && b->rchild==NULL)
        return 1;
    else{
        num1=LeafNodes(b->lchild);
        num2=LeafNodes(b->rchild);
        return (num1+num2);
    }

}

完整程式碼如下:

//BinaryTreeBase.h
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct node{
    ElemType data;     //資料元素
    struct node* lchild;  //指向左孩子
    struct node* rchild;  //指向右孩子
}BTNode;

//由str串建立二叉鏈
void CreateBTNode(BTNode *&b,char *str){
    BTNode *St[MaxSize],*p=NULL;
    int top=-1,k,j=0;
    char ch;
    b=NULL;
    ch=str[j];
    while (ch!='\0')
    {
        switch(ch){
        case '(': top++; St[top]=p; k=1; break;
        case ')': top--; break;
        case ',': k=2; break;
        default: p=(BTNode *)malloc(sizeof(BTNode));
            p->data=ch; p->lchild=p->rchild=NULL;
            if(b==NULL)
                b=p;
            else{
                switch(k){
                case 1: St[top]->lchild=p; break;
                case 2: St[top]->rchild=p; break;
                }
            }
        }
        j++;
        ch=str[j];
    }

}

//返回data域為x的結點指標
BTNode *FindNode(BTNode *b,ElemType x){
    BTNode *p;
    if(b==NULL)
        return NULL;
    else if(b->data==x)
        return b;
    else{
        p=FindNode(b->lchild,x);
        if(p!=NULL)
            return p;
        else
            return FindNode(b->rchild,x);
    }

}

BTNode *LchildNode(BTNode *p){
    return p->lchild;
}

BTNode *RchildNode(BTNode *p){
    return p->rchild;
}

//求二叉樹b的深度
int BTNodeDepth(BTNode *b){
    int lchilddep,rchilddep;
    if(b==NULL)
        return 0;
    else{
        lchilddep=BTNodeDepth(b->lchild);
        rchilddep=BTNodeDepth(b->rchild);
        return (lchilddep>rchilddep)?(lchilddep+1):(rchilddep+1);
    }

}

//用括號表示法輸出二叉樹
void DispBTNode(BTNode *b){
    if (b!=NULL)
    {
        printf("%c",b->data);
        if (b->lchild!=NULL || b->rchild!=NULL)
        {
            printf("(");
            DispBTNode(b->lchild);
            if(b->rchild!=NULL) printf(",");
            DispBTNode(b->rchild);
            printf(")");
        }
    }

}

void printBTN(BTNode *b,int w){
    int i;
    if (b!=NULL)
    {
        printBTN(b->rchild,w+5);
        for(i=1;i<w;i++)
            printf(" ");
        printf("%c\n",b->data);
        printBTN(b->lchild,w+5);
    }

}

//求二叉樹b的寬度
int BTWidth(BTNode *b){
    struct{
        int lno;        //結點的層次編號
        BTNode *p;      //結點指標
    }Qu[MaxSize];      //定義順序非迴圈佇列
    int front,rear;
    int lnum,max,i,n;
    front=rear=0;      //置佇列為空
    if (b!=NULL)
    {
        rear++;
        Qu[rear].p=b;      //根結點指標入隊
        Qu[rear].lno=1;    //根結點的層次編號為1
        while (rear!=front)  //佇列不為空
        {
            front++;
            b=Qu[front].p;    //隊頭出隊
            lnum=Qu[front].lno;
            if (b->lchild!=NULL)  //左孩子入隊
            {
                rear++;
                Qu[rear].p=b->lchild;
                Qu[rear].lno=lnum+1;
            }
            if (b->rchild!=NULL)  //右孩子入隊
            {
                rear++;
                Qu[rear].p=b->rchild;
                Qu[rear].lno=lnum+1;
            }
        }
        max=0; lnum=1; i=1;
        while (i<=rear)
        {
            n=0;
            while (i<=rear && Qu[i].lno==lnum)
            {
                n++; i++;
            }
            lnum=Qu[i].lno;
            if(n>max) max=n;
        }
        return max;
    }
    else
        return 0;

}

//求二叉樹b的結點個數
int Nodes(BTNode *b){
    int num1,num2;
    if(b==NULL)
        return 0;
    else if(b->lchild==NULL && b->rchild==NULL)
        return 1;
    else{
        num1=Nodes(b->lchild);
        num2=Nodes(b->rchild);
        return (num1+num2+1);
    }

}

//求二叉樹b的葉子結點個數
int LeafNodes(BTNode *b){
    int num1,num2;
    if(b==NULL)
        return 0;
    else if(b->lchild==NULL && b->rchild==NULL)
        return 1;
    else{
        num1=LeafNodes(b->lchild);
        num2=LeafNodes(b->rchild);
        return (num1+num2);
    }

}

//主函式.cpp
#include "BinaryTreeBase.h"
#include <stdio.h>

void main()
{
    BTNode* bt;
    char str[20]="A(B(D(,G)),C(E,F))";
    CreateBTNode(bt,str);
    printf("二叉樹的括號表示法:");
    DispBTNode(bt);
    printf("\n");

    printf("橫向列印二叉樹:\n");
    printBTN(bt,10);
    printf("\n");

    int num=0,leafNum=0,deepth=0,width=0;
    num=Nodes(bt);
    leafNum=LeafNodes(bt);
    deepth=BTNodeDepth(bt);
    width=BTWidth(bt);

    printf("二叉樹的結點數: %d\n",num);
    printf("二叉樹的葉子結點數: %d\n",leafNum);
    printf("二叉樹的深度: %d\n",deepth);
    printf("二叉樹的寬度: %d\n",width);

}

效果如下:

這裡寫圖片描述

圖(1) 用括號表示法,建立二叉樹,並求它的深度、寬度和葉子結點數