1. 程式人生 > >二叉樹的線索化及其前驅後繼查詢

二叉樹的線索化及其前驅後繼查詢

一 實質

遍歷二叉樹過程中用線索(前驅和後繼)取代空指標的的做法


二 演算法分析(給出中序化):

主要是增加倆個指標,pre指標始終指向剛剛訪問過的節點,p指標始終指向當前訪問的節點其中,*pre是*p的前驅,*p是*pre的後繼

三 中序線索化演算法:

//將二叉樹按中序線索化演算法
typedef enum   {Link,Thread} PointerTag;//列舉值分別為0,1
typedef struct node
{
    DataType data;
    PointerTag ltag,rtag;   //左右標誌
    struct node *lchild ,*rchild;
}BinThrNode;//線索二叉樹節點型別
typedef BinThrNode *BinThrTree;
void InorderThreading(BinThrTree p)
{//將二叉樹p中序線索化
    if(p)//p非空時,當前訪問結點是*p
    {
        InorderThreading(p->lchild);//左子樹線索化
        //建立正在訪問節點的前驅結點之間的線索
        t->ltag = (t->lchild)?Link:Thread;
        t->rtag = (t->rchild)?Link:Thread;
        if(pre)
        {
            if(pre->rtag==Thread)
                pre->rchild = p;
            if(p->ltag==Thread)
                p->lchid = pre;
        }
        pre = p;
        InorderThreading(t->rchild);//右子樹線索化
    }
}

演算法分析:和中序遍歷一樣遞迴過程對每個節點僅做一次訪問,因此對於n個節點的二叉樹演算法複雜度為O(n)

四 前驅和後繼的查詢

BinThrNode *InorderSuccessor(BinThrNode *p)
{//在中序線索樹查詢*p的後繼
    BinThrNode *q;
    if(p->rtag==Thread)
        return p->rchlid;//返回其所指的後繼
    else
    {
        q = p->rchild;//從*p的右孩子開始查詢
        while(q->ltag==Link)
            q = q->lchild;//左子樹為空,沿左鏈往下查詢
        return q;
    }
}
 BinThrNode *Inorderpre(BinThrNode *p)
      {//在中序線索樹中找結點*p的中序前趨,設p非空
         BinThrNode *q;
        if (p->ltag==Thread) //*p的左子樹為空
               return p->lchild; //返回左線索所指的中序前趨
         else{
               q=p->lchild; //從*p的左孩子開始查詢
               while (q->rtag==Link)
                    q=q->rchild; //右子樹為空時,沿右鏈往下查詢
               return q; //當q的右子樹為空時,它就是最右下結點
             } //end if
      }

從上面可以看出,對與非線索二叉樹,查詢其節點十分困難需要遍歷,而線索二叉樹加入了前驅和後繼之後是這種查詢變得簡單易行