后序線索二叉樹


后序線索二叉樹中,結點的后繼:

  如果結點的雙親有右孩子,則結點的后繼為雙親的右子樹中第一個被訪問的結點

  如果結點的雙親沒有右孩子,則結點的后繼為雙親

  如果結點為雙親的右孩子,則結點的后繼為雙親

因為找到后序遍歷中,找到結點的后繼需要知道節點的雙親,所以可以用三叉鏈表(trifurcate linked list)來存儲結點

 

1.后序線索化二叉樹(用三叉鏈表存儲結構、有頭結點)

void postThreading(TriTree p){
    if(p){
        postThreading(p->lChild);
        postThreading(p->rChild);
        if(!p->lChild){
            p->lTag=1;
            p->lChild=pre;
        }
        if(!pre->rChild){
            pre->rTag=1;
            pre->rChild=p;
        }
        pre=p;
    }
}

bool postThreadTree(TriTree T,TriTree &head){
    if(!(head=new TriTNode)) return false;
    head->lTag=0;
    head->rTag=1;
    head->parent=NULL;
    if(!T){head->lChild=head;head->rChild=head;}
    else{
        pre=head;
        head->lChild=T;
        head->rChild=T;
        T->parent=head;
        postThreading(T);
        if(!pre->rChild){
            pre->rTag=1;
            pre->rChild=head;
        }
    }
    return true;
}

 

2.遍歷后序線索二叉樹

void postTraverseTriTree(TriTree head){
    TriTree p=head->lChild;
    int tag=0;
    while(p->parent!=NULL){
        while(p->lTag==0&&tag==0){p=p->lChild;}
        if(p->rTag==1){//結點無右孩子,可以順着線索訪問后繼 
            visit(p->data);
            while(p->rTag==1&&p->rChild->parent!=NULL){
                p=p->rChild;
                visit(p->data);
            }
        }else if(tag==0){//結點有右孩子且右孩子還沒被訪問過 
            p=p->rChild;
            continue;
        }else{//結點有右孩子且右孩子已經被訪問過 
            visit(p->data);
        }
        //p已經訪問掉了,繼續找p的后繼 
        if(p==p->parent->rChild){p=p->parent;tag=1;}
        else if(p->parent->rTag==0){p=p->parent->rChild;tag=0;}
        else{p=p->parent;tag=1;}
    }
}

 

3.刪除后序線索二叉樹的內存空間 在刪除掉雙親的一個孩子時,將雙親對應的孩子指針置為NULL

void deleteTriTree(TriTree &head){
    TriTree p=head,q=NULL;
    while(p->parent!=NULL){
        while(p->lChild&&p->lTag==0){
            p=p->lChild;
        }
        q=p;
        while(p->rTag==1&&p->rChild->parent!=NULL){
            p=p->rChild;
            if(q->parent->lChild==q) q->parent->lChild=NULL;
            else q->parent->rChild=NULL;
            delete q;
            q=p;
        }
        if(p==p->parent->rChild){
            q=p;
            p=p->parent;
            delete q;
            p->rChild=NULL;
        }else if(p->parent->rChild){
            q=p;
            p=p->parent->rChild;
            q->parent->lChild=NULL;
            delete q;
        }else{
            q=p;
            p=p->parent;
            delete q;
            p->lChild=NULL;
        }
    }
    delete head;
    head=NULL;
}

 

4.用 三叉鏈表存儲結構+前序序列+中序序列 構建二叉樹

bool preAndInCreateTriTree(TriTree &p,TriTree parent,int *preOrder,int *inOrder,int length){
    if(length>0){
        if(!(p=new TriTNode)) return false;
        p->data=preOrder[0];
        p->lTag=0;
        p->rTag=0;
        p->parent=parent;
        int i;
        for(i=0;i<length&&inOrder[i]!=preOrder[0];++i);
        preAndInCreateTriTree(p->lChild,p,preOrder+1,inOrder,i);
        preAndInCreateTriTree(p->rChild,p,preOrder+i+1,inOrder+i+1,length-i-1);    
    }else{
        p=NULL;
    }
    return true;
}

 

 

測試代碼:

#include<iostream>
using namespace std;

typedef struct TriTNode{//trifurcate linked list tree node
    struct TriTNode *lChild,*rChild,*parent;
    int data,lTag,rTag;
}TriTNode,*TriTree;

TriTree pre=NULL;

void visit(int val){
    cout<<val<<" ";
}

bool preAndInCreateTriTree(TriTree &p,TriTree parent,int *preOrder,int *inOrder,int length){
    if(length>0){
        if(!(p=new TriTNode)) return false;
        p->data=preOrder[0];
        p->lTag=0;
        p->rTag=0;
        p->parent=parent;
        int i;
        for(i=0;i<length&&inOrder[i]!=preOrder[0];++i);
        preAndInCreateTriTree(p->lChild,p,preOrder+1,inOrder,i);
        preAndInCreateTriTree(p->rChild,p,preOrder+i+1,inOrder+i+1,length-i-1);    
    }else{
        p=NULL;
    }
    return true;
}

int main(){
    int n,*preOrder,*inOrder;
    
    cout<<"Input the number of nodes : ";
    cin>>n;
    
    preOrder=new int[n];
    inOrder=new int[n];
    cout<<"Input the pre-order sequence : "<<endl;
    for(int i=0;i<n;++i) cin>>preOrder[i];
    cout<<"Input the in-order sequence : "<<endl;
    for(int i=0;i<n;++i) cin>>inOrder[i];
    
    TriTree T;
    TriTree head;
    if(!preAndInCreateTriTree(T,NULL,preOrder,inOrder,n)){
        cout<<"Fail to construct this tree"<<endl;
    }else{
        postThreadTree(T,head);
        cout<<"\nPost-traverse:"<<endl;
        postTraverseTriTree(head);    
    }
    deleteTriTree(head);
    T=NULL;
}

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM