1. 程式人生 > >資料結構——二叉樹的建立、遍歷、求度數、深度

資料結構——二叉樹的建立、遍歷、求度數、深度

二叉樹的建立直接用遞迴操作即可

二叉樹的遍歷有三種

  • 先序遍歷DLR:根節點->左子樹->右子樹
  • 中序遍歷LDR:左子樹->根節點->右子樹。必須要有中序遍歷才能得到一棵二叉樹的正確順序
  • 後續遍歷LRD:左子樹->右子樹->根節點。需要棧的支援。
  • 特殊的遍歷方法就是層次遍歷,即按照二叉樹每一層列印

獲取葉子數目

    直接判斷每個節點的下一結點是否為空即可

求二叉樹的深度

    用遞迴演算法分別求二叉樹的左右子樹的深度,取最大值

求二叉樹的度數

設定num為全域性變數,即每次遍歷一個結點,num加1

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 100

//二叉樹
typedef struct node{
    char data;//資料域
    struct node *lchild,*rchild;//指標域
}BinTree;

//線索二叉樹
typedef struct ThreadTNode{
    int lTag,rTag;//左右標誌域
    char data;//資料域
    struct ThreadTNode *lchild,*rchild;//左右孩子指標域
}ThreadTNode,*ThreadTree;

//建立普通二叉樹
BinTree *creatTree()
{
    BinTree *Tree = NULL;
    char ch;
    ch = getchar();//輸入一個字元
    if(ch != '#')
    {
        Tree = (BinTree*)malloc(sizeof(BinTree));//分配空間
        Tree->data = ch;
        Tree->lchild = creatTree();//建立左子樹
        Tree->rchild = creatTree();//建立右子樹
    }
    return Tree;
}

/*先序遍歷二叉樹*/
void preorder(BinTree *Tree)
{
    if(Tree)//二叉樹不為空
    {
        printf("%c",Tree->data);//輸出節點的值
        preorder(Tree->lchild);//遍歷左子樹
        preorder(Tree->rchild);//遍歷右子樹
    }
}

/*中序遍歷二叉樹*/
void inorder(BinTree *Tree)
{
    if(Tree)//二叉樹不為空
    {
        inorder(Tree->lchild);//遍歷左子樹
        printf("%c",Tree->data);//輸出節點的值
        inorder(Tree->rchild);//遍歷右子樹
    }
}

/*後序遍歷二叉樹*/
void postorder(BinTree *Tree)
{
    if(Tree)//二叉樹不為空
    {
        postorder(Tree->lchild);//遍歷左子樹
        postorder(Tree->rchild);//遍歷右子樹
        printf("%c",Tree->data);//輸出節點的值
    }
}

/*中序輸出二叉樹非遞迴演算法*/
void inorderTraverse(BinTree *bt)
{
    BinTree *stack[MAXSIZE],*p;//定義順序棧stack,最大值為100
    int top = 0;//定義棧頂指標
    p = bt;
    do
    {
        while(p != NULL)//順著左鏈搜尋到盡頭
        {
            stack[top++] = p;//當二叉樹不為空時根指標入棧
            p = p->lchild;//順著左鏈搜尋
        }
        if(top > 0)
        {
            p = stack[top-1];//棧不為空時取出棧頂元素
            printf("%c",stack[top-1]->data);//輸出當前訪問的根節點
            top--;
            p = p->rchild;//順著右鏈搜尋
        }
    }
    while(top != 0||p != NULL);//當遍歷沒有結束時繼續訪問
}

/*獲取葉子數目*/
void getLeafNumber(BinTree *T,int *count)
{
    if(T)
    {
        if((!T->lchild)&&(!T->rchild))//左右孩子都為空
        {
            (*count)++;//對葉子數目計數
        }
        getLeafNumber(T->lchild,count);
        getLeafNumber(T->rchild,count);
    }
}

/*獲取二叉樹的深度*/
int getDepth(BinTree *T)
{
    int higthLeft,highRight;
    if(!T)
        return 0;
    else
    {
        higthLeft = getDepth(T->lchild);
        highRight = getDepth(T->rchild);
        if(higthLeft >= highRight)
            return higthLeft+1 ;
        else
            return highRight+1 ;
    }
}

/*建立線索二叉樹的中序線索連結串列*/
ThreadTree pre;//pre定義全域性變數,始終指向當前節點的前驅
ThreadTree inorderThread(ThreadTree bt)
{
    ThreadTree head;//建立二叉樹bt的中序線索連結串列
    head = (ThreadTree)malloc(sizeof(ThreadTNode));
    if(head)
    {
        printf("分配記憶體錯誤\n");
        return NULL;
    }
    head->lTag = 0; head->rTag = 1;//設定頭結點的線索標誌域
    head->rchild = head;//頭結點右指標指向自身
    if(bt == NULL)
        head->lchild = head;//若二叉樹bt為空,左線索指向自身
    else
    {
        head->lchild = head;//若二叉樹非空則左線索指向二叉樹根節點bt處
        pre = head;//pre指向當前節點的前驅
        inorderThread(bt);//中序遍歷進行中序線索化
        pre->rchild = head;//最後一個節點右線索化
        pre->rTag = 1;//最後一個節點標誌域置為線索
        pre->rchild = pre;//頭結點的右指標指向最後一個節點
    }
    return head;
}


int main()
{
    int number = 0;
    BinTree *T = creatTree();
    printf("先序遍歷二叉樹結果\n");
    preorder(T);
    printf("\n");
    printf("中序遍歷二叉樹結果\n");
    inorder(T);
    printf("\n");
    printf("後序遍歷二叉樹結果\n");
    postorder(T);
    printf("\n");
    printf("中序輸出二叉樹非遞迴演算法\n");
    inorderTraverse(T);
    printf("\n");
    printf("獲取葉子數目\n");
    getLeafNumber(T,&number);
    printf("%d",number);
    printf("\n");
    printf("獲取二叉樹的深度\n");
    printf("%d",getDepth(T));
    printf("\n");
    //ThreadTNode *T;
    return 0;
}