编程基础 - 线索二叉树 (Threaded 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