[数据结构笔记] 线索二叉树

线索链表
 

线索:将二叉链表中的空指针域指向前驱结点和后继结点的指针被称为线索;

线索化:使二叉链表中结点的空链域存放其前驱或后继信息的过程称为线索化;

线索二叉树:加上线索的二叉树称为线索二叉树。

[数据结构笔记] 线索二叉树_第1张图片

结点结

[数据结构笔记] 线索二叉树_第2张图片

enum flag {Child, Thread}; 
template  
struct ThrNode
{
     T data;
     ThrNode  *lchild, *rchild;
     flag ltag, rtag;
};

线索二叉树

二叉树的遍历方式有4种,故有4种意义下的前驱和后继,相应的有4种线索二叉树:

⑴ 前序线索二叉树

⑵ 中序线索二叉树

⑶ 后序线索二叉树

⑷ 层序线索二叉树

中序线索链表类的声明

template 
class InThrBiTree{    
   public:
        InThrBiTree();     
         ~ InThrBiTree( );    
        ThrNode *Next(ThrNode *p); 
        void InOrder(ThrNode *root); 
   private:
        ThrNode *root;  
        ThrNode *  Creat(); 
        void ThrBiTree(ThrNode *root);
};

中序线索链表的建立——构造函数

分析:建立线索链表,实质上就是将二叉链表中的空指针改为指向前驱或后继的线索,而前驱或后继的信息只有在遍历该二叉树时才能得到。

template ThrNode* InThrBiTree::Creat( ){
    ThrNode *root;
    T ch;
    cout<<"请输入创建一棵二叉树的结点数据"<>ch;
    if (ch=="#") root = NULL;
    else{	
         root=new ThrNode;    
         root->data = ch;
         root->ltag = Child; root->rtag = Child;
         root->lchild = Creat( );
         root->rchild = Creat( ); 
    } 
	return root;
}

建立带有标志位的二叉链树

template ThrNode* InThrBiTree::Creat( ){
    ThrNode *root;
    T ch;
    cout<<"请输入创建一棵二叉树的结点数据"<>ch;
    if (ch=="#") root = NULL;
    else{	
         root=new ThrNode;    
         root->data = ch;
         root->ltag = Child; root->rtag = Child;
         root->lchild = Creat( );
         root->rchild = Creat( ); 
    } 
	return root;
}

中序线索化二叉树:递归实现

基本思想:

在遍历的过程中完成线索化

可以采用前序、中序、后序遍历建立前序线索二叉树、中序线索二叉树和后序线索二叉树。

中序线索二叉树的构造方法

中序线索化根结点的左子树;

对根结点进行线索化;

中序线索化根结点的右子树;

算法分析

函数设置形参root全局变量pre,分别表示要处理的树的根结点和其前驱结点

如果root!=NULL

中序线索化root的左子树

中序线索化root本身

如果root->lchild==NULL

 root->left=pre,root->ltag=1;

如果root->rchild==NULL,root->rtag=1,

如果pre=NULL 并且pre->rtag=1

pre->rchild=root,;

pre=root

中序线索化root的右子树

template   void ThrBiTree::ThrBiTree (ThrNode*root) {
      if (root==NULL) return;         //递归结束条件
   
      ThrBiTree(root->lchild); 	
if (!root->lchild){             //对root的左指针进行处理
        root->ltag = Thread;   
        root->lchild = pre;        //设置pre的前驱线索
   }
  if (!root->rchild) root->rtag = Thread; 

  if(pre != NULL){
       if (pre->rtag==Thread)  pre->rchild = root; 
  }
   pre = root;
   ThrBiTree(root->rchild);
}

线索二叉树的建立

ThrNode* pre = NULL

template 
InThrBiTree::InThrBiTree( )
{ 
	//ThrNode* pre = NULL;
	this->root = Creat( );    
	ThrBiTree(root);
}

线索链表的遍历算法:中序遍历中序线索树

从中序序列中的第一个结点出发,进行遍历

?如何确定中序序列的第一个节点?

依次找前一个节点的后继

?如何确节点的后继?

查找第一个节点

先从穿线树的根出发,一直沿左指针,找到最左(它一定是中序的第一个结点)

结点后继的确定

一个结点的右指针如果是线索,则右指针就是下一个要遍历的结点,

如果右指针不是线索,则它的中序后继是其右子树的最左结点

遍历何时停止?

一个节点的右指针==NULL

在中序线索树中查找结点的中序遍历的后继

结点后继的确定

一个结点的右指针如果是线索,则右指针就是下一个要遍历的结点,

如果右指针不是线索,则它的中序后继是其右子树的“最左”结点

template  ThrNode* InThrBiTree::Next(ThrNode* p)
{
    ThrNode* q;  //要查找的p的后继
    if (p->rtag==Thread)   q = p->rchild;
    else{   
        q = p->rchild; 
        while (q->ltag==Child)	{
            q = q->lchild;
        }
    }
    return q;
}

线索链表的遍历算法:中序遍历中序线索树

template  
void InThrBiTree::InOrder(ThrNode *root){
    ThrNode* p = root;
    if (root==NULL)  return; 
    while (p->ltag==Child)   {       p = p->lchild;    }
    cout<data<<" ";
    while (p->rchild!=NULL) {
        p = Next(p);
        cout<data<<" ";
    }
    cout<

 

你可能感兴趣的:(数据结构)