编程基础 - 线索二叉树 (Threaded Binary Tree)

本文介绍了线索二叉树的基础知识,通过C++代码展示了如何为二叉树的节点添加线索,以及如何进行中序遍历。线索二叉树利用空指针存储前驱和后继节点,方便遍历操作。
摘要由CSDN通过智能技术生成

编程基础 - 线索二叉树 (Threaded Binary Tree)

返回分类:全部文章 >> 基础知识

返回上级:编程基础 - 二叉树 (Binary Tree)

本文将介绍线索二叉树的基础知识,并用C++实现它。

在查看本文之前,需要一些数据结构和程序语言的基础,要对“树”和“二叉树 (Binary Tree)”的概念有一些了解。

其中的方法还需要熟悉“栈(stack)”、“队列(queue)”和“递归”。



1 线索二叉树简述 (Introduction)

线索二叉树:假设有 n 个结点的二叉树,其中存在 n + 1 个空指针,利用这些指针存放某种遍历下的前驱和后继,这样的指针叫做线索,这样形成的二叉树叫线索二叉树。

线索二叉树分为三种:

  • 中序线索二叉树
  • 前序线索二叉树
  • 后续线索二叉树

之后的代码,我们用中序线索二叉树来举例,另外两种原理相同,不再阐述。


2 线索二叉树的结构 (Structure)

在结构中,我们左子树与右子树需要一个标签来标注存放的是左右孩子还是前驱后继。

且对于每个结点的空指针域:

  • 左子树指针空:存放前驱指针
  • 右子树指针空:存放后继指针
// Author: https://blog.csdn.net/DarkRabbit
// Threaded Binary Tree

// 线索标签,标记指针存放的是左右孩子还是前驱后继
enum ThreadTag
{
   
    LeftOrRightChild = 0, // 左孩子或右孩子
    PredecessorOrSuccessor = 1 // 前驱或后继
};

// 线索二叉树节点
template<typename T>
class ThreadNode
{
   
    public:
    T element; // 数据
    ThreadTag leftTag; // 左标签
    ThreadTag rightTag; // 右标签
    ThreadNode<T>* leftChild; // 左指针
    ThreadNode<T>* rightChild; // 右指针

    ThreadNode(const T& e)
    {
   
        element = e;
        leftTag = ThreadTag::LeftOrRightChild;
        rightTag = ThreadTag::LeftOrRightChild;
        leftChild = 0;
        rightChild = 0;
    }
    ~ThreadNode()
    {
   
        leftChild = 0;
        rightChild = 0;
    }
};

3 为结点加入线索 (Add Thread)

初始化二叉树不再介绍,这里我们为每个结点加入线索。

由于我们需要保存前驱和后继,所以需要一个变量predNode来存储上一个结点。

而加入线索,我们需要对所有节点遍历。即,只是将二叉树的中序遍历中将访问节点(Visit)换成了加入线索。

对于每个结点的空指针域:

  • 左子树指针空:存放前驱指针
  • 右子树指针空:存放后继指针

C++代码:

  • 递归方式:

    // Author: https://blog.csdn.net/DarkRabbit
    // Threaded Binary Tree
    // 递归初始化中序遍历线索
    template<typename T>
    void InitializeInorderThread(ThreadNode<T>* node, ThreadNode<T>*& predNode)
    {
         
        if (node != 0)
        {
         
            // 左标识
            if (node->leftChild == 0)
            {
         
                node->leftTag = ThreadTag::PredecessorOrSuccessor;
            }
            else
            {
         
                node->leftTag = ThreadTag::LeftOrRightChild;
            }
    
            // 右标识
            if (node->rightChild == 0)
            {
         
                node->rightTag = ThreadTag::PredecessorOrSuccessor;
            }
            else
            {
         
                node->rightTag = ThreadTag::LeftOrRightChild;
            }
    
            InitializeInorderThread(node->leftChild, predNode); // 左子树(L)
            
            // 左子树为空,则NULL或前驱
            if (node->leftTag == ThreadTag::PredecessorOrSuccessor)
            {
         
                node->leftChild = predNode;
            }
    
            // 如果前驱存在,且右子树为空,则NULL或后继
            if (predNode != 0 && predNode->rightTag 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值