线索二叉树

线索二叉树的运算 

在中根线索树上查找某结点的前趋和后继 
(1) 已知 q 结点,找出它的前趋结点。
  根据线索树的基本概念,当 q->ltag = 1 时, q->lch 就指向 q 的前趋。当 q->ltag=0 时,表明 q 有左孩子。由中根遍历的规律可知,做为根 q 的前趋结点 ( 或者说以根结点为后继的结点 ) ,它应是中根遍历 q 的左子树时 , 所访问的最后一个结点,即左子树的最右尾结点。请看图 6.12(c) ,结点 B 是 A 的左子树的最右尾结点, B 就是 A 的前趋结点。而 B 的后继指针指向了 A , A 就是 B 的后继结点。若用 p 指针记录 q 的前趋前趋结点,求 q 的前趋结点的算法如下:

ThreNode*inpre(ThreNode *q)
 { ThreNode *p,*r;
  if(q->ltag==1)p=q->lch;    //找到q的前驱
  else{ r=q->lch;     //在q的左子树,找最右尾结点
        while(r->rtag!=1)r=r->rch;
        p=r;
   }
 returnp;
 }
(2) 已知 q 结点,找出它的后继结点。
  当 q->rtag = 1 时, q->rch 即指向 q 的后继结点。若 q->rt = 0 ,表明 q 有右孩子,那么 q 的后继应是中序遍历 q 的右子树时 , 访问的第一个结点,即右子树的最左结点。看图 6.12(c) , A 的后继为 F , C 的后继为 H 。若用 p 记录 q 后继结点,算法如下:

ThreNode *ThTree::insucc(ThreNode *q)
 { ThreNode *p,*r;
   if(q->rtag==1)p=q->rch;
   else{r=q->rch;
        while(r->ltag!=1)r=r->lch;
        p=r;
       }
   returnp;
 }

在中根线索树上遍历二叉树
  遍历某种次序的线索二叉树,只要从该次序下的开始结点开发,反复找到结点在该次序下的后继,直至终端结点。
  遍历中序线索二叉树算法:
void ThTree::inthorder()
 { ThreNode *p;
   p=root;
   if(p!=NULL)
   while(p->lch!=NULL)p=p->lch;    //查找树的最左结点
   cout<<"\n  "<<p->data;
   while(p->rch!=NULL){p=insucc(p);
   cout<<"  "<<p->data;
 };
}
 分析:
  ① 中序序列的终端结点的右线索为空,所以do语句的终止条件是p==NULL。
  ② 该算法的时间复杂性为O(n)。因为是非递归算法,常数因子上小于递归的遍历算法。因此,若对一棵二叉树要经常遍历,或查找结点在指定次序下的前趋和后继,则应采用线索链表作为存储结构为宜。
  ③ 以上介绍的线索二叉树是一种全线索树(即左右线索均要建立)。许多应用中只要建立左右线索中的一种。
  ④ 若在线索链表中增加一个头结点,令头结点的左指针指向根,右指针指向其遍历序列的开始或终端结点会更方便。

你可能感兴趣的:(数据结构,二叉树,C语言)