后序线索二叉树中,结点的后继:

  如果结点的双亲有右孩子,则结点的后继为双亲的右子树中第一个被访问的结点

  如果结点的双亲没有右孩子,则结点的后继为双亲

  如果结点为双亲的右孩子,则结点的后继为双亲

因为找到后序遍历中,找到结点的后继需要知道节点的双亲,所以可以用三叉链表(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;
}

 

 

 

 

 

版权声明:本文为NoerForest原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/NoerForest/p/14613441.html