线索二叉树

反思

今天本来准备写图论的笔记,可是仔细一想,线索二叉树我好像还不是很会。

其实我本来是不打算认真看线索二叉树的,一来是因为线索二叉树实在是长了一副不太能用到的样子(太难打啦,还麻烦),而来我也没有看出来线索二叉树有什么奇怪的功能(那个功能遍历一遍不就可以了吗)。

所以一直都搁置了。可是转眼一想,还是有点后悔,因为自己如果懒到连课本上有的内容都不学好,还怎么学习非课本上的拓展内容呢?自己连这点高标准都不留给自己,还怎么继续学习,考研谁敢要?

所以经过我的深思熟虑,我觉得还是仔细的弄一遍线索二叉树比较好。

线索二叉树的存储结构

具体应用:知道某个节点在某种遍历中的前驱和后继。

实现方法:对任意节点,若左指针域为空,则用左指针域存储该节点的前驱线索,若右指针域为空,则用该指针域存储该节点的后继线索。

节点的定义如下:

struct Node
{
    char data;
    int ltag,rtag;//标记,是否是存储的前驱后继,可设定为,为0存储孩子,为1存储前驱后继。
    Node *l,*r;//存储左右孩子或者前驱后继
};
    

本文讲述中序线索二叉树,前序后序变化不大。

线索链表的实现

(1)构造函数

创建二叉树的步骤与普通的二叉树不同之处在于标记的初始化,这里统一将标记初始化为0。

这里的构造函数不仅仅有二叉树的创建,最重要的是二叉链表的线索化(线索化建立在二叉树已经建立完成的基础上)。

具体实现思想为:

  1. 函数设置形参root和全局变量pre,分别表示要处理的树的根结点和其前驱结点(因为同一个时间点前驱只能有一个,所以可以用全局变量,再说不用全局变量写不了啊)。
  2. 如果root==NULL,return;
  3. 如果root!=NULL,中序线索化root的左子树,中序线索化root本身
  4. 如果root->lchild==NULL 则root->left=pre,root->ltag=1;
  5. 如果root->rchild==NULL,root->rtag=1,如果pre!=NULL,并且pre->rtag=1,pre->rchild=root;//root是pre的后继
  6. pre=root
  7. 中序线索化root的右子树
void ThrBiTree::ThrBiTree (Node *root) {
    if (root==NULL) 
        return;         //递归结束条件
    ThrBiTree(root->lchild); 	
    if (!root->lchild){       //对root的左指针进行处理
        root->ltag =1;   
        root->lchild = pre;      //设置pre的前驱线索
    }
    if (!root->rchild) 
        root->rtag =1; 
    if(pre != NULL){
        if (pre->rtag==1)  pre->rchild = root; 
    }
    pre = root;
    ThrBiTree(root->rchild);
}

(2)中序遍历查找后继

分两种情况:

①节点p的右标记为1,则说明右指针是线索,他就是后继

②节点p的右标记为0,说明他有右孩子,不能直接找到其后继节点。

根据中序遍历的操作定义,它的后继节点应当是遍历其右子树时第一个节点->右子树最左下的节点

所以沿着其右孩子的左指针往下找,某个节点没有左孩子时(即ltag=0),就是所需的后继节点。

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

(3)中序遍历

找到第一个节点,依次遍历后继即可。

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

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值