中序線索二叉樹----查找指定結點在後序的前驅結點

【題目描述】

寫出在中序線索二叉樹裏查找指定結點在後序的前驅結點的算法。

【分析】

這道題目的前提是我們已經有了中序線索二叉樹。在二叉樹後序序列中,對於結點p,其前驅依次有可能是:①p的右孩子②沒有右孩子,那就可能是左孩子③沒有孩子,那就可能是其父結點的左孩子④否則,可能是其爺爺結點的左孩子,以此類推。

對於①②,特判即可。對於③,中序線索二叉樹中,p無左孩子,則其左指針域指向其父,故可向上訪問,直到有一個祖先有左孩子,則這個左孩子一定是後序遍歷p的前驅。

注意中序序列第一個結點無前驅,其在後序中亦無前驅,需要特判。

【樣例】

測試樣例先序建樹:ABD##E##C#FG##H##

【測試完整代碼】

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

struct node{
	char data;
	int ltag,rtag;
	struct node *lchild,*rchild;
};

struct node *node_arr[100]; //保存下所有結點的指針
int node_arr_top=0;
struct node* createTree()  //先序建樹,樣例ABD##E##C#FG##H##
{
	char ch=getchar();
	if(ch!='#'){
		struct node* p=(struct node*)malloc(sizeof(struct node));
		node_arr[++node_arr_top]=p; //保存指針
		p->data = ch;
		p->lchild = createTree();
		p->rchild = createTree();
        p->ltag = p->rtag = 0;
		return p;
	}
	return NULL;
}

//二叉樹中序線索化
void convertToXiansuo(struct node *root, struct node **last)
{
    if(root)
    {
        convertToXiansuo(root->lchild,last);  //線索化左子樹
        if(root->lchild==NULL){          //讓左指針指向前驅
            root->lchild=*last;
            root->ltag=1;
        }
        if((*last)!=NULL && (*last)->rchild==NULL){ //root作爲後繼,被last右指針所指
            (*last)->rtag=1;
            (*last)->rchild=root;
        }
        *last = root;
        convertToXiansuo(root->rchild,last); //線索化右子樹
    }
}

void xianSuoHua(struct node *root)  //中序線索化
{
    struct node *last=NULL; //最先訪問的結點的前驅就是NULL
    convertToXiansuo(root,&last);
    last->rtag=1;   //最後訪問的結點沒有後繼,但也要標記右指針
}


struct node* preOfBackOrder(struct node* p)  //求後序序列中p的前驅
{
    if(p==NULL)return NULL;           //p空,不存在前驅
    if(p->rtag==0)return p->rchild;   //有右孩子
    if(p->ltag==0)return p->lchild;   //無右,但有左孩子
    //剩下的情況:所求必爲p的最近的<祖先的左孩子>
    while(p&&p->ltag==1)              //p無左孩子,訪問其父(即中序前驅)
        p=p->lchild;
    if(p)return p->lchild;            //找到了
    return NULL;                      //不存在
}


int main()
{
    int i;
    printf("請輸入先序序列以建樹: "); //樣例:ABD##E##C#FG##H##
    struct node* root=createTree();
    xianSuoHua(root);
    for(i=1;i<=node_arr_top;i++)    //輸出每個結點的信息
    {
        struct node* p=node_arr[i];
        //*printf("%d  %9d  %c  %9d  %d\n",p->ltag,p->lchild,p->data,p->rchild,p->rtag);

        struct node* r=preOfBackOrder(p);
        printf("後序序列中%c的前驅是%c\n",p->data,r?r->data:'-');
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章