【樹】遍歷算法應用

輸出二叉樹中的結點

【算法思想】
輸出二叉樹中的結點並無次序要求,因此可用三種遍歷算法中的任何一種完成,只需將訪問操作具體變爲輸出操作即可。下面給出採用先序遍歷實現的算法。
【算法描述】

void PreOrder(BiTree root)
/* 先序遍歷輸出二叉樹結點, root 爲指向二叉樹根結點的指針 */
{
    if (root != NULL)
    {
        printf("%c", root->data); /* 輸出根結點 */
        PreOrder(root->LChild);   /* 先序遍歷左子樹 */
        PreOrder(root->RChild);   /* 先序遍歷右子樹 */
    }
}
輸出二叉樹中的葉子結點

【算法思想】
輸出二叉樹中的葉子結點與輸出二叉樹中的結點相比,它是一個有條件的輸出問題,即在遍歷過程中走到每一個結點時需進行測試,看是否滿足葉子結點的條件。
【算法描述】

void PreOrder(BiTree root)
/* 先序遍歷輸出二叉樹中的葉子結點 , root 爲指向二叉樹根結點的指針 */
{
    if (root != NULL)
    {
        if (root->LChild == NULL && root->RChild == NULL)
            printf("%c", root->data); /* 輸出葉子結點 */
        PreOrder(root->LChild);       /* 先序遍歷左子樹 */
        PreOrder(root->RChild);       /* 先序遍歷右子樹 */
    }
}
統計葉子結點數目
  • 方法一

【算法思想】
統計二叉樹中的葉子結點數目並無次序要求,因此可用三種遍歷算法中的任何一種完成,只需將訪問操作具體變爲判斷是否爲葉子結點及統計操作即可。
【算法描述】

/* LeafCount 爲保存葉子結點數目的全局變量,調用之前初始化值爲 0 */
void leaf(BiTree root)
{
    if (root != NULL)
    {
        leaf(root->LChild);
        leaf(root->RChild);
        if (root->LChild == NULL && root->RChild == NULL)
            LeafCount++;
    }
}
  • 方法二

【算法思想】
給出求葉子點數目的遞歸定義:
1)如果是空樹,返回 0;
2)如果只有一個結點,返回 1;
3)否則爲左右子樹的葉子結點數之和。
【算法描述】

int leaf(BiTree root)
{
    int LeafCount;
    if (root == NULL)
        LeafCount = 0;
    else if ((root->LChild == NULL) && (root->RChild == NULL))
        LeafCount = 1;
    else /* 葉子數爲左右子樹的葉子數目之和 */
        LeafCount = leaf(root->LChild) + leaf(root->RChild);
    return LeafCount;
}
建立二叉鏈表方式存儲的二叉樹
  • 給定一棵二叉樹,我們可以得到它的遍歷序列;
  • 反過來,給定一棵二叉樹的遍歷序列,我們也可以創建相應的二叉鏈表。

這裏所說的遍歷序列是一種“擴展的遍歷序列”。在通常的遍歷序列中,均忽略空子樹,而在擴展的遍歷序列中,必須用特定的元素表示空子樹。例如,圖中二叉樹的“擴展先序遍歷序列”爲:AB.DF…G…C.E.H… 其中用小圓點表示空子樹。在這裏插入圖片描述
【算法思想】
採用類似先序遍歷的遞歸算法,首先讀入當前根結點的數據,如果是“.”則將當前樹根置爲空,否則申請一個新結點,存入當前根結點的數據,分別用當前根結點的左子域和右子域進行遞歸調用,創建左、右子樹。
【算法描述】

void CreateBiTree(BiTree *bt)
{
    char ch;
    ch = getchar();
    if (ch == '.')
        *bt = NULL;
    else
    {
        *bt = (BiTree)malloc(sizeof(BiTNode));
        (*bt)->data = ch;
        CreateBiTree(&((*bt)->LChild));
        CreateBiTree(&((*bt)->RChild));
    }
}
求二叉樹的高度

二叉樹的高度(深度)爲二叉樹中結點層次的最大值,也可視爲其左、右子樹高度的最大值加 1。
【算法思想】
二叉樹 bt 高度的遞歸定義如下

  • 若 bt 爲空,則高度爲 0。
  • 若 bt 非空,其高度應爲其左、右子樹高度的最大值加 1,如下圖所示。
    在這裏插入圖片描述
    【算法描述】
int PostTreeDepth(BiTree bt) /* 後序遍歷求二叉樹 bt 高度的遞歸算法 */
{

    int hl, hr, max;
    if (bt != NULL)
    {
        hl = PostTreeDepth(bt->LChild); /* 求左子樹的深度 */
        hr = PostTreeDepth(bt->RChild); /* 求右子樹的深度 */
        max = hl > hr ? hl : hr;        /* 得到左、右子樹深度較大者*/
        return (max + 1);               /* 返回樹的深度 */
    }
    else
        return (0); /* 如果是空樹,則返回 0 */
}

求二叉樹的高度是也可用前序遍歷的方式實現。
【算法思想】
二叉樹的高度(深度)爲二叉樹中結點層次的最大值。設根結點爲第一層的結點,所有 h 層的結點的左、右孩子結點在 h+1 層。故可以通過遍歷計算二叉樹中的每個結點的層次,其中最大值即爲二叉樹的高度。
【算法描述】

void PreTreeDepth(BiTeee bt, int h)
/* 先序遍歷求二叉樹 bt 高度的遞歸算法,h 爲 bt 指向結點所在層次,初值爲 1*/
/*depth 爲當前求得的最大層次,爲全局變量,調用前初值爲 0 */
{
    if (bt != NULL)
    {
        if (h > depth)
            depth = h;                   /*如果該結點層次值大於 depth,更新 depth的值*/
        PreTreeDepth(bt->Lchild, h + 1); /* 遍歷左子樹 */
        PreTreeDepth(bt->Rchild, h + 1); /* 遍歷右子樹 */
    }
}
按樹狀打印二叉樹
假設以二叉鏈表存儲的二叉樹中,每個結點所含數據元素均爲單字母。 要求實現二叉樹的橫向顯示問題,如下圖所示打印結果。

在這裏插入圖片描述

【算法思想】
(1)二叉樹的橫向顯示應是二叉樹豎向顯示的 90。旋轉。分析上圖示可知,這種樹形打印格式要求先打印右子樹,再打印根,最後打印左子樹,按由上而下順序看,其輸出的結點序爲:CFEADB,這恰爲逆中序順序。解決二叉樹的橫向顯示問題採用“逆中序”遍歷框架,所以橫向顯示二叉樹算法爲先右子樹、再根結點、再左子樹的 RDL 結構。
(2)在這種輸出格式中,結點的左、右位置與結點的層深有關,故算法中設置了一個表示當前根結點層深的參數,以控制輸出結點的左、右位置,每當遞歸進層時層深參數加 1。這些操作應在訪問根結點時實現。
【算法描述】

void PrintTree(BiTree bt, int nLayer)
/* 按豎向樹狀打印的二叉樹 */
{
    if (bt == NULL)
        return;
    PrintTree(bt->RChild, nLayer + 1);
    for (int i = 0; i < nLayer; i++)
        printf(“ ”);
    printf(% c\n”, bt->data);
    /*按逆中序輸出結點,用層深決定的左、右位置*/
    PrintTree(bt->LChild, nLayer + 1);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章