輕鬆讓你徹底搞定c++版 線索二叉樹的線索化演算法

牛掰是怎麼形成的發表於2017-11-11

這裡寫圖片描述
二叉樹圖

首先我們要先談談線索二叉樹資料結構的出現理由,為什麼要出現。我們可以不用線索二叉樹嗎,那是肯定的。

談線索二叉樹之前你必須對二叉樹的鏈式儲存結構遍歷非常瞭解。

如果不瞭解請先搞懂先,

我們知道二叉樹的節點資料型別有如下幾種設計孩子雙親節點,我就談這一種設計。

孩子雙親那就說明這個節點資料儲存了孩子和雙親的地址,可以立馬找到當前節點的孩子和雙親,但是如果我想不用遍歷就得到比如中序遍歷後的當前節點的前序和後序節點。

那麼我們在不改變比如我們當前節點型別的設計結構上,怎麼做,才讓我們可以輕鬆拿到節點的中序遍歷後的前後驅節點呢。

這個時候線索二叉樹就誕生了,我們肯定知道我們的二叉樹資料型別肯定並且不是完全二叉樹,也許很多二叉樹節點的指標域都是空的,是不是浪費了,這個時候我們可以把這些空的指標利用起來。我們可以儲存中序遍歷後的前後驅節點。

我們這裡是針對中序遍歷的前後驅,並且設計的節點資料型別比較簡單,僅僅是當前節點資料+ 孩子節點的地址指標,現在問題來了既然節點指標域既可以儲存他的孩子節點,又可以儲存線索也就是中序遍歷的前或者後驅節點地址。

那麼我們可以必須設計新節點的資料型別


//設計二叉樹的節點資料型別
typedef struct BiTree
{
    //節點資料
    int data;

//左孩子的指標變數
    struct BiTree* lChild, *rChild;

int lTag, rTag; // 規則:0表示當前節點左指標域儲存的是左孩子地址 1儲存是當前節點的前驅節點線索

}*BiTree;


我們首先個約定:約定lTag這個變數取01並且是針對當前節點的左孩子指標變數,至於這個變數儲存的是左孩子節點還是前驅節點,我們可以根據是 0 還是1  我們預設儲存左孩子節點 這個時候標誌lTag = 0,

rTag這個是針對右指標 0表示存的是節點的右孩子節點   1表示存的是後驅節點


下面上具體程式碼。我們採用的是遞迴演算法線索化二叉樹。也就是把空指標域裡面填上線索的過程。

//中序遍歷二叉樹併線索化 root:儲存了二叉樹物件的根節點地址
void InitThread(BiTree root)
{
//開闢臨時變數儲存當前遍歷的節點地址
BiTree temp = root;

//判斷二叉樹是不是為空
if(root != null)
{
     //先遞迴呼叫自身線索化當前節點的左子樹  由於是中序遍歷
     InitThread(root->lChild);

     /*開始線索化當前節點*/
      先線索化當前節點前驅節點
     if(root->lChild == null)
     {
        //設定標誌位  表明當前節點存的是線索而不是孩子節點地址
        root->lTag = 1;

        //開始真正線索化
        root->lChild = pre;     //根據中序遍歷我們知道當前訪問的節點就是其左孩子的前驅節點
     }

     //開始當前節點的後驅線索化
     if(pre != null && pre->rChild == null)
     {
          //開始設計標誌為 表示當前右指標域存的是線索不是右孩子節點
          pre->rTag = 1;

          //後驅線索化真正開始
          pre->rChild = root; 
     }

    //遞迴右孩子線索化
    InitThread(root->rChild);
}

}
“`

相關文章