数据结构与算法笔记——二叉树递归线索化要注意的问题

614 阅读3分钟

一、中序线索化

中序线索二叉树是不会出现前驱节点pre的右孩子和当前节点p的左孩子同时为空的情况如图1,也即代码中标注的两个if语句不会同时成立

中序遍历线索二叉树的结果如图2

通过中序遍历对二叉树线索化的递归算法
typedef struct ThreadNode{
  char data;
  struct ThreadNode *lchild,*rchild;
  int ltag,rtag;

}ThreadNode,*ThreadTree;


void InThread(ThreadTree &p,ThreadTree &pre){
    if(p!=NULL){
        InThread(p->lchild,pre);//递归,线索化左子树
        if(p->lchild==NULL){
            p->lchild = pre;
            p->ltag = 1;
        }
        if(pre!=NULL&&pre->rchild==NULL){//中序线索化中两个 if 语句不会同时成立
            pre->rchild = p;
            pre->rtag = 1;
        }

        pre=p;
        InThread(p->rchild,pre);//递归,线索化右子树
    }//end p!=NULL

}

void CreateInThread(ThreadTree T){
     ThreadTree pre = NULL;
      if(T!=NULL){
        InThread(T,pre);
        pre->rchild=NULL;//这里不需要判断最后一个节点是否为空就可直接处理
        pre->rtag=1;//因为中序遍历的最后一个节点必须是叶子节点,叶子节点无左右孩子
      }
}

二、前序线索化

前序线索二叉树会出现前驱节点pre的右孩子和当前节点p的左孩子同时为空的情况但并不是两种情况都会存在,即如果存在只能是图3左边这种情况,如图3所示

前序遍历线索二叉树的结果如图4,由于会出现上数的第一种情况,我们必须要对代码进行处理,否则前序线索化的程序会无线递归下去

通过前序遍历对二叉树线索化的递归算法
void PreThread(ThreadTree &p,ThreadTree &pre){
    if(p!=NULL){//前序线索化中两个 if 语句会同时成立
     if(p->lchild==NULL){
            p->lchild = pre;
            p->ltag = 1;
        }
        if(pre!=NULL&&pre->rchild==NULL){
            pre->rchild = p;
            pre->rtag = 1;
        }

        pre=p;
        if(p->ltag==0)//只有左孩子不是线索时才线索化左子树
        PreThread(p->lchild,pre);//递归,线索化左子树
        PreThread(p->rchild,pre);
    }//end p!=NULL

}

void CreatePreThread(ThreadTree T){
     ThreadTree pre = NULL;
      if(T!=NULL){
        PreThread(T,pre);
        if(pre->rchild=NULL)//这里不需要判断最后一个节点是否为空就也可直接处理
        pre->rtag=1;//因为中序遍历的最后一个节点必须是叶子节点,叶子节点无左右孩子
      }
}

三、后序线索化

后序线索二叉树会出现前驱节点pre的右孩子和当前节点p的左孩子同时为空的情况但并不是两种情况都会存在,即如果存在只能是图5右边这种情况,如图5所示

后序遍历线索二叉树的结果如图6,后序因为先递归再处理,所以不会出现无限递归的现象,故无需特殊处理

通过后序遍历对二叉树线索化的递归算法
void PostThread(ThreadTree &p,ThreadTree &pre){

        PostThread(p->lchild,pre);//递归,线索化左子树
        PostThread(p->rchild,pre);

    if(p!=NULL){//后序线索化中两个 if 语句会同时成立
      if(p->lchild==NULL){
            p->lchild = pre;
            p->ltag = 1;
        }
        if(pre!=NULL&&pre->rchild==NULL){
            pre->rchild = p;
            pre->rtag = 1;
        }

        pre=p;
    }//end p!=NULL

}

void CreatePostThread(ThreadTree T){
     ThreadTree pre = NULL;
      if(T!=NULL){
        PreThread(T,pre);
        if(pre->rchild=NULL)//这里需要判断最后一个节点是否为空
        pre->rtag=1;
      }
}