1. 程式人生 > >資料結構——線索二叉樹(程式碼)

資料結構——線索二叉樹(程式碼)

線索二叉樹

C++ 環境codeblocks17 通過

/*
線索二叉樹
@CGQ 2018/10/29
*/
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;
#define ElemType char

typedef struct BiTNode
{
    ElemType data;
    struct BiTNode *lchild, *rchild;
    int LTag,RTag;  // Tag 為0表示指向左右孩子,為1表示指向前驅和後繼
}BiTNode, *BiTree;

BiTree pre;// 全域性變數pre,記錄節點前驅,初始時指向線索樹的頭節點(非樹根)

void CreateBiTree(BiTree &T)
{// 先序建立二叉樹
    ElemType ch;
    cin>>ch;
    if(ch == '#')
        T = NULL;
    else
    {
        T = new BiTNode;
        T->data = ch;
        T->LTag = 0;    // 標誌位置0,表示指向左右孩子(可以不要,在InThreading()中賦值)
        T->RTag = 0;
        CreateBiTree(T->lchild);
        CreateBiTree(T->rchild);
    }
}

void InThreading(BiTree T)
{// 中序線索化
    if(T)
    {
        InThreading(T->lchild); // 左子樹遞迴線索化
        if(!T->lchild)  // T的左孩子為空
        {
            T->LTag = 1;    // 給T加上左線索
            T->lchild = pre;    // T的左孩子指向pre(前驅)
        }
        else T->LTag = 0;
        if(!pre->rchild)    //pre 的右孩子為空
        {
            pre->RTag = 1;  // 給pre加上右線索
            pre->rchild = T;    // pre的左孩子指向T(後繼)
        }
        else pre->RTag = 0;
        pre = T;
        InThreading(T->rchild);  // 右子樹遞迴線索化
    }
}

void InOrderThreading(BiTree &THead, BiTree T)
{// //中序遍歷二叉樹T, 線索化,THead 指向頭節點
    THead = new BiTNode;    // 建立頭節點
    THead->LTag=0;  // 頭節點的左孩子指向樹根
    THead->RTag=1;  // 頭節點有孩子為線索指標
    THead->rchild=THead;    // 初始化時右指標指向自己
    if(!T) THead->lchild=THead; // 樹非空,則左指標也指向自己
    else
    {
        THead->lchild=T; pre = THead;   // 頭節點左孩子指向樹根,pre指向頭節點
        InThreading(T); // 中序線索化二叉樹
        pre->rchild=THead;  // 線索化結束後,pre為最右節點,pre的右線索指向頭節點
        pre->RTag=1;
        THead->rchild=pre;   // 頭節點右線索指向最右節點
    }
}

void InOrderTraverse_Thr(BiTree &T)
{// 中序遍歷二叉樹,非遞迴
    BiTree p = T->lchild;   // p指根節點
    while(p != T)
    {
        while(p->LTag==0)   // 沿左孩子一直向下
            p=p->lchild;
        cout<<p->data<<" "; //訪問左子樹為空的節點

        while(p->RTag==1&&p->rchild!=T) // 沿著右線索訪問後續節點
        {
            p=p->rchild;
            cout<<p->data<<" ";
        }

        p = p->rchild;  // 當p沒有右線索時,轉向p的右子樹
    }
}

int main()
{
    BiTree T=NULL,THead;
    CreateBiTree(T);    // 建立
    InOrderThreading(THead,T);  // 線索化
    InOrderTraverse_Thr(THead); // 遍歷
    return 0;
}

/*
測試資料:
AB#CD###EF##HI##G##
        A
       / \
      B   E
       \  /\
        C F H
       /    /\
      D    I  G
ABD##E##CF##G##
        A
       / \
      B   C
      /\  /\
      D E F G
HDA##C#B##GF##ER##T##

*/