一、前言:什么是二叉树的线索化?(为什么要有二叉树的线索化?)
- 通过前面内容的学习,我们知道了二叉树的存储结构其实是通过二叉链表的方式实现的。但二叉链表由于每个结点均有左右孩子域,这使得叶子结点以及部分非叶子结点出现了孩子指针域为空的情况。
如图例:
- 可以发现的是,随着二叉树结点个数 的增长,二叉树中空指针域的个数越来越多,这会造成不小的存储空间浪费。
- 假设,现在需要你求解一个节点的前驱节点/后续节点,你要如何进行呢?
- 通过遍历方法我们确实可以知道二叉树中某个结点的前驱和后继分别是谁,但是这是建立在二叉树遍历的基础上的。一旦二叉树遍历结束后,如果想要知道二叉树中某个结点的前驱或后继时,得从头结点开始遍历二叉链表,这将会造成不小的时间开销。
- 如图中的二叉链表如果我想要找到 的前驱是谁,得遍历一遍二叉树才能搞定
- 既然有那么多空指针域,为什么不能把这些空指针域利用起来,让每个空指针域用来记录当前结点的前驱呢?这样一来,是不是就解决了空指针域造成的存储空间浪费以及查找前驱后继时时造成的时间浪费呢?
因此,二叉线索树诞生了
二、二叉线索树的概念
2.1:名词解释
- 让二叉树中的空指针域记录二叉树某种遍历次序下的前驱和后继结点的地址,这样的话,再想找二叉树中某个结点的前驱后继时间性能将大为提升。
- 这种将二叉链表中指向前驱后继的指针称为线索,加上线索的二叉链表称之为线索链表,线索链表所对应的二叉树称之为线索二叉树(Threaded Binary Tree)。
三、二叉线索树的实现
3.1:二叉线索树的基本数据结构
typedef struct ThreadedTreeNode {
// 线索化二叉树节点
eleType val;
struct ThreadedTreeNode* left; // 左指针
struct ThreadedTreeNode* right; // 右指针
int leftTag; // 左标志位:0 表示指向左子树,1 表示指向前驱
int rightTag; // 右标志位:0 表示指向右子树,1 表示指向后继
} ThreadedTreeNode;
//leftTag和rightTag默认为0
eleType val
:存储节点的值,根据宏定义,这里是char
类型。 -struct ThreadedTreeNode* left
:指向左子节点的指针。struct ThreadedTreeNode* right
:指向右子节点的指针。int leftTag
:标志位,0
表示left
指针指向左子树,1
表示left
指针指向前驱节点。int rightTag
:标志位,0
表示right
指针指向右子树,1
表示right
指针指向后继节点。
3.2:初始化节点
// 初始化节点
ThreadedTreeNode* Init_Node(eleType val)
{
ThreadedTreeNode* node = (ThreadedTreeNode*)malloc(sizeof(ThreadedTreeNode));
node->val = val;
node->left = NULL;
node->right = NULL;
node->leftTag = 0;
node->rightTag = 0;
return node;
}
ThreadedTreeNode* Init_Node(eleType val)
:一个函数,用于初始化一个ThreadedTreeNode
节点。ThreadedTreeNode* node = (ThreadedTreeNode*)malloc(sizeof(ThreadedTreeNode));
:为新节点分配内存空间。node->val = val;
:将传入的值存储到节点的val
成员中。node->left = NULL;
和node->right = NULL;
:将左右子节点指针初始化为NULL
。node->leftTag = 0;
和node->rightTag = 0;
:将左右标志位初始化为0
,表示它们初始时都指向左右子树。return node;
:返回初始化好的节点指针。
3.3:创建一个普通二叉树
// 创建普通二叉树(同前面代码中一样,略去重复部分)
ThreadedTreeNode* CreateTree(eleType a[], int size, int index, eleType nullNode)
{
if (index >= size || a[index] == nullNode)
{
return NULL;
}
ThreadedTreeNode* root = Init_Node(a[index]); //初始化节点
root->left = CreateTree(a, size, 2 * index + 1, nullNode); //递归创建二叉树
root->right = CreateTree(a, size, 2 * index + 2, nullNode);
return root;
}
ThreadedTreeNode* CreateTree(eleType a[], int size, int index, eleType nullNode)
:一个递归函数,用于根据数组元素创建普通二叉树。if (index >= size || a[index] == nullNode)
:如果当前索引超出数组范围或元素等于nullNode
,返回NULL
,表示该位置无节点。ThreadedTreeNode* root = Init_Node(a[index]);
:创建当前位置的节点。root->left = CreateTree(a, size, 2 * index + 1, nullNode);
:递归创建左子树。root->right = CreateTree(a, size, 2 * ind