數據結構——樹的相關算法實現

二叉樹的基本算法

包括二叉樹的遍歷(先、中、後),二叉樹的層次,二叉樹的深度,二叉樹的葉子節點數計算。相關算法思想能夠看書,這裏只是給出相關算法實現。node

代碼實現

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 30

typedef char ElemType;

typedef struct TNode {
    char data;
    TNode * lchild; 
    TNode * rchild;
}TNode, *BiTree;


int IsEmpty_BiTree(BiTree *T) {
    if(*T == NULL)
    return 1;//若是樹爲空一直進入死循環,直到輸入數據爲止 
    else
    return 0;
}

void Create_BiTree(BiTree *T){
    char ch;
    ch = getchar();
    //當輸入的是"#"時,認爲該子樹爲空
    if(ch == '#')
        *T = NULL;
    //建立樹結點
    else{
        *T = (BiTree)malloc(sizeof(struct TNode));
        (*T)->data = ch; //生成樹結點
        //生成左子樹
        Create_BiTree(&(*T)->lchild);
        //生成右子樹
        Create_BiTree(&(*T)->rchild);
    }
}

void TraverseBiTree(BiTree T) { //先序遍歷 
    if(T == NULL)//指針爲空,說明節點不存在 
    return; 
    else {
        printf("%c ",T->data);
        TraverseBiTree(T->lchild);
        TraverseBiTree(T->rchild);
    }
    
}

void InOrderBiTree(BiTree T) {      //中序遍歷 
    if(NULL == T)
    return;
    else {
        InOrderBiTree(T->lchild);
        printf("%c ",T->data);
        InOrderBiTree(T->rchild);   
    }
}

void PostOrderBiTree(BiTree T) {
    if(NULL == T)
    return;
    else {
        InOrderBiTree(T->lchild);
        InOrderBiTree(T->rchild);
        printf("%c ",T->data);
    }
    
} 

int TreeDeep(BiTree T) {
    int deep = 0;
    if(T)
    {
        int leftdeep = TreeDeep(T->lchild);
        int rightdeep = TreeDeep(T->rchild);
        deep = leftdeep+1 > rightdeep+1 ? leftdeep+1 : rightdeep+1; 
    }
    return deep;
}
//樹的葉子結點爲 
int Leafcount(BiTree T, int &num) {//通常涉及到變化的都會取地址 
    if(T)
    {
        if(T->lchild ==NULL && T->rchild==NULL) 
        {
            num++;
            printf("%c ",T->data);
        }           
        Leafcount(T->lchild,num);
        Leafcount(T->rchild,num);

    }
    return num;
}

//樹的層次顯示 (利用隊列,先進先出的原則能夠完美實現) 
void LevelOrder_BiTree(BiTree T){
    //用一個隊列保存結點信息,這裏的隊列採用的是順序隊列中的數組實現
    int front = 0;
    int rear = 0;
    BiTree BiQueue[MAXSIZE];
    BiTree tempNode;
    if(!IsEmpty_BiTree(&T)){
        BiQueue[rear++] = T;
         
        while(front != rear){// 
            //取出隊頭元素,並使隊頭指針向後移動一位 
            tempNode = BiQueue[front++];
            //判斷左右子樹是否爲空,若不爲空,則加入隊列 
            if(!IsEmpty_BiTree(&(tempNode->lchild)))
                BiQueue[rear++] = tempNode->lchild;
             
            if(!IsEmpty_BiTree(&(tempNode->rchild)))
                BiQueue[rear++] = tempNode->rchild;
             
             printf("%c ",tempNode->data);
        }
    }
}

int main(void)
{
    BiTree T;
    BiTree *p = (BiTree*)malloc(sizeof(BiTree));
    int deepth,num=0 ;
    Create_BiTree(&T);//通常涉及到變化的都會取地址 
    printf("先序遍歷二叉樹:\n");
    TraverseBiTree(T);
    printf("\n");
    printf("中序遍歷二叉樹:\n");
    InOrderBiTree(T);
    printf("\n");
    printf("後序遍歷二叉樹:\n");
    PostOrderBiTree(T);
    printf("\n層次遍歷結果:");
    LevelOrder_BiTree(T);
    printf("\n");
    deepth=TreeDeep(T);
    printf("樹的深度爲:%d",deepth);
    printf("\n");
    printf("樹的葉子結點爲:");
    Leafcount(T,num);
    printf("\n樹的葉子結點個數爲:%d",num);
    return 0;
}

運行演示

線索二叉樹的中序遍歷

#include<iostream>
#include <stdlib.h>
using namespace std;

typedef struct BiThrNode
{
    char data;
    struct BiThrNode *lchild,*rchild;      /*左右孩子指針*/
    int LTag,RTag;                          /*左右標誌*/
}BiThrNode,*BiThrTree;

BiThrTree pre;



void CreateBiTree(BiThrTree *T){
    char ch;
    ch = getchar();
    //當輸入的是"#"時,認爲該子樹爲空
    if(ch == '#')
        *T = NULL;
    //建立樹結點
    else{
        *T = (BiThrTree)malloc(sizeof(struct BiThrNode));
        (*T)->data = ch; //生成樹結點
        //生成左子樹
        CreateBiTree(&(*T)->lchild);
        //生成右子樹
        CreateBiTree(&(*T)->rchild);
    }
}

/*以結點p爲根的子樹中序線索化*/
void InThreading(BiThrTree p)
{
    /*pre是全局變量,初始化時其右孩子指針爲空,便於在樹的最左點開始建線索*/
    if(p)
    {
        InThreading(p->lchild);            /*左子樹遞歸線索化*/
        if(!(p->lchild) )                      /*p的左孩子爲空*/
        {                  
            p->LTag=1;                     /*給p加上左線索*/
            p->lchild=pre;                 /*p的左孩子指針指向pre(前驅)*/
        }
        else
        {
            p->LTag=0;
        }
        if(!(pre->rchild) )                  /*pre的右孩子爲空*/
        {
            pre->RTag=1;                  /*給pre加上右線索*/
            pre->rchild=p;                /*pre的右孩子指針指向p(後繼)*/
        }
        else
        {
            pre->RTag=0;
        }
        pre=p;                            /*保持pre指向p的前驅*/
        InThreading(p->rchild);           /*右子樹遞歸線索化*/
    }
}
/*帶頭結點的中序線索化*/
void InOrderThreading(BiThrTree &Thrt,BiThrTree T)
{
    /*中序遍歷二叉樹T,並將其中序線索化,Thrt指向頭結點*/
    Thrt=new BiThrNode;         /*建頭結頭*/
    Thrt->LTag=0;               /*頭結點有左孩子,若樹非空,則其左孩子爲樹根*/       
    Thrt->RTag=1;               /*頭結點的右孩子指針爲右線索*/
    Thrt->rchild=Thrt;          /*初始化時右指針指向本身*/
    if(!T) Thrt->lchild=Thrt;   /*若樹爲空,則左指針也指向本身*/
    else
    {
        Thrt->lchild=T; pre=Thrt; /*頭結點的左孩子指向根,pre初值指向頭結點*/
        InThreading(T);          /*調用上述算法,對以T爲根的二叉樹進行中序線索化*/
        pre->rchild=Thrt;        /*算法結束後,pre爲最右結點,pre的右線索指向頭結點*/
        pre->RTag=1;
        Thrt->rchild=pre;        /*頭結點的右線索指向pre*/
    } 
}  
/*遍歷中序線索二叉樹*/
void InOrderTraverse_Thr(BiThrTree T)
{
    /*T指向頭結點,頭結點的左鏈lchild指向根結點*/
    /*中序遍歷二叉線索樹T的非遞歸算法,對每一個數據元素直接輸出*/
    BiThrTree p=T->lchild;    /*p指向根結點*/        
    while(p!=T)
    {
        while(p->LTag == 0)      /*沿左孩子向下*/
        {
             p=p->lchild;
        }
        cout<<p->data<<" ";           /*訪問其左子樹爲空的結點*/
        while(p->RTag == 1 && p->rchild!=T)  /*沿右線索訪問後繼結點*/
        {
            p=p->rchild;
            cout<<p->data<<" ";
        }
        p=p->rchild;
    }
    cout<<p->data;
}
int main()
{
    BiThrTree T;
    BiThrTree Thrt;
    cout<<"Input the Threaded BinaryTree 's node:"<<endl;
    CreateBiTree(&T);
    InOrderThreading(Thrt,T); /*帶頭結點的中序線索化*/
    cout<<"InOrderTraverse_Thr:"<<endl;
    InOrderTraverse_Thr(T);   /*遍歷中序線索二叉樹*/
    return 0;
}

運行演示

二叉樹結構圖

參考文獻

  • 數據結構-用C語言描述(第二版)[耿國華]
相關文章
相關標籤/搜索