1. 程式人生 > >圖解二叉樹及二叉樹遍歷

圖解二叉樹及二叉樹遍歷

二叉樹及二叉樹遍歷

  • 完全二叉樹
  • 二叉樹的遍歷
  • 遍歷的性質

1、完全二叉樹

對於一棵具有n個節點的二叉樹(按層序編號),如果編號為i的節點與同樣深度的滿二叉樹中編號為i的節點在二叉樹的位置完全相同,則為完全二叉樹。

換句話來說,如果每個節點按照滿二叉樹的結構逐層順序進行編號,如果編號出現編號空擋,就說明不是完全二叉樹,否則就是。如下圖所示:

這裡寫圖片描述

左邊二叉樹按照完全二叉樹進行編號,出現了10號的空擋,右邊二叉樹出現了6,7號的空擋,所以以上兩棵樹都不是完全二叉樹。

2、二叉樹的遍歷

二叉樹的遍歷主要包括前序遍歷、中序遍歷、後序遍歷和層序遍歷四種,其中前三種是非常常用的,下面主要介紹前三種遍歷的方法。

  • 前序遍歷

若二叉樹為空,則空操作返回,否則先訪問根節點,然後前序遍歷左子樹,再前序遍歷右子樹。如下圖所示:

這裡寫圖片描述

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

其實前序遍歷的技巧還可以有如下方式:

這裡寫圖片描述

1、從根節點的左邊開始,繞過所有節點和邊,畫出一條封閉的、有向的遍歷曲線(如上圖紅色所示)。

2、對於每個節點,曲線第一次從連線進入節點的位置標記為1,最後一次從節點出去的位置標記為2 。

3、如上圖的標記所示,沿著遍歷曲線的方向,依次經過標記為1的節點為前序遍歷序列:ABEFIJCDGH 。

  • 中序遍歷

若二叉樹為空,則空操作返回,否則從根節點開始(注意不是先訪問根節點),中序遍歷根節點的左子樹,然後是訪問根節點,最後中序遍歷右子樹。如下圖所示:

這裡寫圖片描述

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

同樣根據上一節前序遍歷的技巧,同樣適用於中序遍歷,但是相對複雜一些:

這裡寫圖片描述

1、對於所有葉子節點,在標記1和2中間加上標記0。

2、當父節點只有左子樹時,在該節點右下方標記0;當父節點只有右子樹時,在該節點的左下方標記0 。

3、當父節點同時有左右子樹時,在其正下方標記0 。

4、沿著遍歷曲線的方向,依次經過標記為0的節點為中序遍歷序列:DGBAECHF 。

  • 後序遍歷

若二叉樹為空,則空操作返回,否則從左到右先葉子後節點的方式遍歷訪問左右子樹,最後是訪問根節點。

這裡寫圖片描述

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

其實後序遍歷的技巧和前序遍歷的基本是差不多的,有如下方式:

這裡寫圖片描述

沿著遍歷曲線的方向,依次經過標記為2的節點為後序遍歷序列:EIJFBCGHDA 。

3、遍歷的性質

兩個二叉樹遍歷的性質:
1、已知前序遍歷和中序遍歷,可以唯一的確定一個二叉樹;
2、已知後序遍歷和中序遍歷,可以唯一的確定一個二叉樹;

但是,已知前序遍歷和後序遍歷,是不能唯一的確定一棵二叉樹的。比如,前序遍歷ABC,後續遍歷CBA,我們可以確定A是根節點,但是無法確定那個是左子樹,哪個是右子樹。

這裡寫圖片描述