1. 程式人生 > >線索二叉樹詳解以及程式碼實現

線索二叉樹詳解以及程式碼實現

參照《大話資料結構》188到194頁。

一、二叉樹的線索儲存結構定義

/* 二叉樹線索儲存結構定義
   Link = 0,代表指向左右孩子的指標
   Thread= 1 代表指向前驅或後繼的線索*/
typedef enum{ Link, Thread} PointerTag;

typedef char TypeData;

typedef struct BiTreeNode
{
    TypeData data;
    struct BiTreeNode *lchild, *rchild;
    PointerTag LTag;
    PointerTag RTag;
}BITREENODE;


二、對二叉樹進行中序遍歷,並把所有的空的左孩子指標指向該節點的前驅,空的右孩子指標指向該節點的後繼。



三、程式碼實現(慢慢去看)

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

/* 二叉樹線索儲存結構定義
   Link = 0,代表指向左右孩子的指標
   Thread= 1 代表指向前驅或後繼的線索*/
typedef enum{ Link, Thread} PointerTag;

typedef char TypeData;

typedef struct BiTreeNode
{
    TypeData data;
    struct BiTreeNode *lchild, *rchild;
    PointerTag LTag;
    PointerTag RTag;
}BITREENODE;


BITREENODE* createBiTree();          /* 建立二叉樹 */
void preOrderBiTree(BITREENODE* T);  /* 前序遍歷該二叉樹 */
void InThreadBiTree(BITREENODE* T);  /* 中序遍歷線索化該二叉樹 */
void InOrderBiTree_Thread(BITREENODE* T); /* 中序遍歷該線索二叉樹 */



/* 建立二叉樹 */
BITREENODE* createBiTree()
{
    TypeData ch = 0;
    BITREENODE* pNewNode = NULL;

    cin >> ch;

    if(ch == '#')
    {
        pNewNode = NULL;
    }
    else
    {
        /* 給節點分配記憶體 */
        pNewNode = (BITREENODE*)malloc(sizeof(BITREENODE));
        pNewNode->data = ch;
        pNewNode->LTag = pNewNode->RTag = Link;

        /* 遞迴構建左右子樹 */
        pNewNode->lchild = createBiTree();
        pNewNode->rchild = createBiTree();
    }

    return pNewNode;
}

/* 前序遍歷該二叉樹 */
void preOrderBiTree(BITREENODE* T)
{
    if(T)
    {
       cout << T->data << " ";
       preOrderBiTree(T->lchild);
       preOrderBiTree(T->rchild);
    }
}

/* 中序遍歷線索化該二叉樹 */
BITREENODE* pre = NULL;  //全域性變數,始終指向剛剛訪問過的節點
void InThreadBiTree(BITREENODE* T)
{
    if(T)
    {
        /* 遞迴線索化左子樹 */
        InThreadBiTree(T->lchild);

        /* 沒有左孩子 */
        if(!T->lchild)
        {
            T->LTag = Thread;  //前驅線索
            T->lchild = pre;   //左孩子指標,指向後繼
        }

        /* 前驅沒有右孩子 */
        if(pre != NULL && pre->rchild == NULL)
        {
            pre->RTag = Thread;  //後驅線索
            pre->rchild = T;     //前驅的右孩子指向後繼
        }

        /* 保持pre指向T的前驅 */
        pre = T;

        /* 遞迴右子樹線索化 */
        InThreadBiTree(T->rchild);
    }
}

/* 中序遍歷該線索二叉樹 */
void InOrderBiTree_Thread(BITREENODE* T)
{
    BITREENODE* p = T;

    while(p != NULL)
    {

        /* 當LTag == 0時迴圈到中序序列第一個節點 */
        while(p->LTag == Link)
        {
            p = p->lchild;
        }

        /*打印出該節點的數值*/
        cout << p->data << " ";

        /* 打印出當前節點的後繼*/
        while(p->RTag == Thread && p->rchild != NULL)
        {
            p = p->rchild;
            cout << p->data << " ";
        }

        /* 指向該節點的後繼 */
        p = p->rchild;
    }

    cout << endl;

}


int main(void)
{
    BITREENODE* pRoot = NULL;

    /* 建立二叉樹 */
    pRoot = createBiTree();

    /* 前序遍歷該二叉樹,這時候還沒有線索化二叉樹,可以這樣進行前序遍歷 */
    preOrderBiTree(pRoot);
    cout << endl;

    /* 中序線索化該二叉樹 */
    InThreadBiTree(pRoot);

    /* 前序遍歷該二叉樹,這時候已經中序線索化了二叉樹,就不可以這樣中序遍歷了 */
   // preOrderBiTree(pRoot);

   InOrderBiTree_Thread(pRoot);

    return 0;
}