线索二叉树之先序线索化

目录

前言

温故知新

先序线索化思路

代码实现

先序线索化代码

先序线索二叉树遍历

遍历思路

先序线索二叉树遍历代码

示例程序

主函数代码 

运行结果



前言

线索二叉树以及线索化的概念,节点改造请见博客线索二叉树剖析【C/C++】

本文将介绍先序线索化二叉树的算法思路以及代码实现

温故知新

线索化的实质就是将二叉链表中的空指针改为指向前驱或后继的线索。由于前驱和后继的信息只有在遍历该二叉树时才能得到,所以线索化的过程就是在遍历的过程中修改空指针的过程。

也就是说,我们只对含孩子指针为空的节点进行改造

先序线索化思路

1、算法整体结构仍是一个先序遍历,只不过遍历过程中对空指针进行改造

2、空指针改造无非指向前驱或者后继,所以我们需要一个指向前驱节点的指针prev

3、对于待改造节点,如果左孩子为空,那么我们需要把它指向当前节点的前驱节点,并且标记左孩子为线索节点

4、对于待改造节点,如果右孩子为空,那么我们需要把它指向当前节点的前驱节点,并且标记右孩子为线索节点

5、当前节点改造完毕,我们需要依次改造仍为非线索节点的左子树右子树

代码实现

先序线索化代码

有没有发现无论是中序线索化还是先序线索化都是在中序/先序遍历中加入了相同的操作

void PrevThreading(BiThrNode *root, BiThrNode *&prev) // 主程序调用该函数时prev为nullptr
{
    if (!root)
        return;
    if (!root->_left)
    {
        // 当前节点左为空,则当前节点左指向前驱也就是prev
        root->_left = prev;
        root->_ltag = PointerTag::Thread;
    }
    if (prev != nullptr && !(prev->_right))
    // 前驱节点右为空,则前驱节点指向后继也就是root
    // 前驱节点的左已经在前驱节点的线索化函数内处理过了
    {
        prev->_right = root;
        prev->_rtag = PointerTag::Thread;
    }
    prev = root;
    if (root->_ltag == PointerTag::Link)
        PrevThreading(root->_left, prev); // 递归线索化左子树

    if (root->_rtag == PointerTag::Link)
        PrevThreading(root->_right, prev); // 递归线索化右子树
}

先序线索二叉树遍历

遍历思路

先序线索二叉树遍历是三种线索二叉树中最简单的一种

如果左节点为link节点,那么我们就一直往左遍历即可

当遍历到左节点为Thread节点,我们就往右一直遍历

先序线索二叉树遍历代码

void PrevOrderTraverse_Thr(BiThrNode *root)
{
    if (!root)
        return;

    while (root)
    {
        // 当_ltag为Link就遍历左子树
        while (root->_left && root->_ltag == PointerTag::Link)
        {
            cout << root->_data << " ";
            root = root->_left;
        }
        cout << root->_data << " ";

        if (root->_ltag == PointerTag::Thread) // 遇到线索,看右节点
            root = root->_right;
        while (root)
        {
            // 当_ltag为Link就退出遍历左子树
            if (root->_ltag == PointerTag::Link && root->_left)
                break;
            cout << root->_data << " ";
            root = root->_right;
        }
    }
}

示例程序

仍以该二叉树为例

主函数代码 

int main()
{
    // 构建示例图二叉树
    BiThrNode *_root = new BiThrNode('A');
    _root->_left = new BiThrNode('B');
    _root->_right = new BiThrNode('C');
    _root->_left->_left = new BiThrNode('D');
    _root->_left->_right = new BiThrNode('E');
    _root->_right->_left = new BiThrNode('F');
    _root->_right->_right = new BiThrNode('G');
    _root->_left->_left->_left = new BiThrNode('H');
    _root->_left->_left->_right = new BiThrNode('I');
    _root->_left->_right->_left = new BiThrNode('J');
    // 线索化前的先序遍历
    cout << "线索化前的先序遍历"
         << ":   ";
    PrevOrder(_root);

    // 线索化后的先序遍历
    BiThrNode *prev = nullptr;

    PrevThreading(_root, prev);
    cout << "线索化后的先序遍历"
         << ":   ";
    PrevOrderTraverse_Thr(_root);
    return 0;
}

运行结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EQUINOX1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值