线索二叉树的深度理解

不知道你是否和我当时同样,对于线索二叉树,有点云里雾里的感受,如今咱们来一块儿探讨下吧。函数

首先,咱们所应该知道的是:线索二叉树是对二叉链表中空指针的充分利用,也就是说,使得本来是空指针的转化成在某种遍历的顺序下,指向该结点的前驱和后继。也许听的有点糊涂,不要紧,请接着往下看。spa

在二叉链表中,每一个结点都带有*leftChild和*rightChild,两个指针,而除根结点外,每一个结点只被一个指针所对应,要么是leftChild,要么是rightChild.而总共有2*n个指针,也就是说,有2*n-(n-1)个空指针,从这个角度,也说明了线索二叉树的必要性。指针

线索二叉树在二叉链表的基础上增长了两个成员数据:leftTag,rightTag;用来标记当前结点的leftChild,rightChild指针指向的是孩子,仍是线索。leftTag=rightTag=1,表示线索,leftTag=rightTag=0;表示孩子;class

下面给出中序遍历顺序下的线索二叉树的构造函数,*p为根;基础

template <class ElemType>二叉树

void InThreadBinTree<ElemType>::InThreadHelp(ThreadBinTreeNode<ElemType> *p,ThreadBinTreeNode<ElemType> *pre)循环

{遍历

       if(p!=NULL)构造函数

     {程序

          InThreadHelp(p->leftChild,pre);

          if(p->leftChild==NULL)

          {

                p->leftChild=pre;

                p->leftTag=1;

           }

          else

          p->leftTag=0;

         if(pre!=NULL&&pre->rightChild==NULL)

         {

             pre->rightChild=p;

             pre->rightTag=1;

         }

         else if(pre!=NULL)

        {

              pre->rightTag=0;

         }

        pre=p;

       InThreadHelp(p->rightChild,pre);

   }

}

该段程序可被分为3部分,1.左孩子的线索化,2.p的线索化,3.p右孩子的线索化。

在中序遍历的前提下,判断p是否有空指针,然而,再遍历右子树以前,若是p->rightChild=NULL是没法肯定p的后继的,所以,此时,只能判断p->leftChild是否为空,若为空,则leftChild=pre;此时,判断pre->rightChild是否为空,如为空,pre->rightChild=p;

p=pre;你也许注意到了,此时pre->rightChild,也就是先前p->rightChild,此时能够判断了,而且后继就是如今的p;此时全部空指针的线索化已经完成。固然,第一个结点的leftchild,和最后一个结点的rightchild是空指针,由于他们不须要线索化。

那么问题又来了,作了这么多,线索二叉树有什么用,或者说要怎么用。

如下是我的理解;

经过构造线索二叉树,咱们能够很容易肯定树中任何一个结点在某种遍历顺序下的前驱或者后继。不妨以中序遍历为例;

树中必然存在这样两种结点:被线索化了的,以及没有被线索化的

被线索化的,leftTag==1,leftchild即为前驱,rightTag==1,rightChild即为后继;

若leftTag==0,则该结点的前驱经过leftchild为根的树的rightchild循环,直到rightTag==1,即为其前驱,

若rightTag==0,则经过rightchild为根的leftchild循环,直到leftTag==1,即为其后继。

也就是说,任何结点按中序遍历的顺序的前驱和后继都能找到。这就是线索二叉树的做用,方便肯定某种遍历的顺序。

相关文章
相关标签/搜索