1. 程式人生 > 其它 >【資料結構-樹】二叉樹的相關演算法

【資料結構-樹】二叉樹的相關演算法

目錄

1 計算二叉樹中雙分支結點的個數

假設二叉樹採用二叉連結串列儲存,試設計一個演算法,計算一棵給定二叉樹的所有雙分支結點個數。

int count = 0;

void Degree2 (BiTree T){
    if (T != NULL){
        Degree2(T->lchild);
        Degree2(T->rchild);
        if ((T->lchild != NULL) && (T->rchild != NULL))
            count++;   
    }
} 

2 交換二叉樹中所有左右子樹

編寫一個把樹 B 中所有結點的左、右子樹進行交換的函式。

void SwapNodeChild (BiTree T){
    if (T->lchild != NULL)
        SwapNodeChild(T->lchild);
    if (T->rchild != NULL)
        SwapNodeChild(T->rchild);

    Swap(T->lchild, T->rchild);
}

3 求先序遍歷第 k 個元素

設計一個演算法,求先序遍歷序列中第 k 個結點的值。

int i = 1;

int PreOrder (BiTree T, int k){
    if (T != NULL){
        if (i == k)
            return T->data;
        i++;
        
        PreOrder(T->lchild, k);
        PreOrder(T->rchild, k);
    }
}

4 刪去值為 x 的子樹

對於樹中每個元素值為 x 的結點,刪去以它為根的子樹,並釋放相應的空間。

void Delete (BiTree T){ // 找到元素值為 x 的結點後,遞迴刪去它的左子樹和右子樹
    if (T != NULL){
        Delete(T->lchild);
        Delete(T->rchild);
        free(T);
    }
}

void Find (BiTree T, int x){
    if (T != NULL){
        if (T->data == x){ // 若找到元素值為 x 的結點
            Delete(T);     // 開始遞迴刪去它的左子樹和右子樹
            return;
        }
        else{ // 若不是元素值為 x 的結點
            Find(T->lchild, x); // 繼續找左子樹中有無元素值為 x 的結點
            Find(T->rchild, x); // 繼續找右子樹中有無元素值為 x 的結點
        }
    }
}

5 計算二叉樹的帶權路徑長度(WPL)

二叉樹的帶權路徑長度(WPL)是二叉樹中所有葉結點的帶權路徑長度之和。給定一棵二叉樹 T,採用二叉連結串列儲存結點結構為

left weight right
左子樹指標域 權值 右子樹指標域

其中葉結點的 weight 域儲存該結點的非負權值,設 root 為指向 T 的根結點的指標,請設計求 T 的 WPL 的演算法。

演算法的核心思想是先序遍歷 + 計算層數,程式碼如下:

int WPL;

void WPL_PreOrder (BiTree T, int level){
    if (T != NULL){
        if ((T->lchild != NULL) && (T->rchild != NULL))
            WPL = WPL + T->weight * level;
        else if ((T->lchild != NULL) && (T->rchild == NULL))
            WPL_PreOrder(T->lchild, level + 1);
        else
            WPL_PreOrder(T->rchild, level + 1);
    }
}

// main 函式中呼叫:
WPL_PreOrder(Tree, 0);

6 將表示式樹轉化為等價的中綴表示式

請設計一個演算法,將給定的表示式樹,轉換成等價的中綴表示式並輸出。

二叉樹結點定義如下:

typedef struct node{
    char data[10];
    struct node *left, * right;
} BTree;

演算法的核心思想是中序遍歷 + 計算層數。可以先將中序遍歷的表示式先寫出來,再與加了括號的表示式對比一下,看看哪個地方加了括號。遍歷左子樹前加上左括號,遍歷完右子樹後加上右括號,根結點(表示式最外層)和葉結點(運算元)不需要加括號。程式碼如下:

void InOrder (BTree *T, int level){
    if (T != NULL){
        if ((T->left == NULL) && (T->right == NULL)) // 葉結點
            輸出 T->data; // 輸出運算元
        else{
            if (level > 1) // 若有子表示式則加 1 層括號
                輸出 "(";
            InOrder(T->left, level + 1);
            輸出 T->data; // 輸出操作符
            InOrder(T->right, level + 1);
            if (level > 1) // 若有子表示式則加 1 層括號
                輸出 ")";
        }
    }
}

// main 函式中呼叫:
InOrder(Tree, 0);