什么是线索二叉树?
我们知道二叉树中有许多节点的left后者right指向nullptr,这样无疑是浪费了存储空间,我们能不能利用这些指向nullptr的指针域给利用起来,做点有利的事情呢?
使用二叉链表存储链表,n个节点的二叉树的指针域有2*n个,但只有n-1个是实指针,其余n+1个都是空指针,因为除了根节点的每个节点都需要双亲存储其地址所以是n-1个实指针。
enum{LINKCHILD,LINEOTHER};
typedef struct BTnode{
;
ElemType datastruct Bnode*lchild,*rchild;
int ltag,rtag;
}BTnode,*BTtree;
//ltag标志lchild指向自己的左孩子,还是指向遍历序列的前驱节点
//rtag标志rchild指向自己的右孩子,还是指向遍历序列的后驱节点
带有标志域的二叉链表称为线索链表
,指向前驱和后继的指针称为线索
,带有线索的二叉树称为线索二叉树
,以某种遍历方式将二叉树转化为线索二叉树的过程称为线索化。
//main1.cpp
#include <iostream>
using namespace std;
enum
{
,
LINKCHILD
LINKOTHER};
typedef struct BTnode
{
int data;
struct BTnode *lchild, *rchild;
int ltag, rtag;
} BTnode, *BTtree;
/**
* @brief 二叉树中序线索化
*
* @param now_node 当前所在节点
* @param pre_node 前驱节点
*/
void InThread(BTnode *&now_node, BTnode *&pre_node)
{
//对当前所在节点线索化
if (now_node)
{
(now_node->lchild, pre_node); //线索化左子树
InThreadif (!now_node->lchild) //如果当前节点的左孩子为空
{
->ltag = LINKOTHER; //标志为线索
now_node->lchild = pre_node; //左孩子指向遍历序列前驱节点
now_node}
else
{
->ltag = LINKCHILD; //标志为非线索
now_node}
//对前驱节点rchild线索化
if (pre_node)
{
if (!pre_node->rchild) //前驱节点的右孩子为空
{
->rtag = LINKOTHER; //将前驱节点的右孩子标记为线索
pre_node->rchild = now_node;
pre_node}
else
{
->rtag = LINKCHILD;
pre_node}
}
= now_node; //将前驱指针指向当前节点
pre_node //线索化右子树
(now_node->rchild, pre_node);
InThread}
}
/**
* @brief 创建中序线索
*
* @param tree
*/
void createInThread(BTtree &tree)
{
*now_node = tree; //指向现在所在的节点
BTnode *pre_node = nullptr; //指向刚才遍历的前一个节点
BTnode if (tree) //树不为空
{
(now_node, pre_node); //中序线索化
InThread//当线索化结束时 now_node为nullptr pre_node指向中序遍历序列的最后一个节点
->rchild = nullptr;
pre_node->rtag = LINKOTHER; //标记为线索
pre_node}
}
/**
* @brief 创建代表标志可以被线索化的二叉树
*
*/
void createBTtree(BTtree &tree)
{
int data;
<< "input data" << endl;
cout >> data;
cin if (data != -1)
{
= new BTnode;
tree ->data = data;
tree//创建左子树
(tree->lchild);
createBTtree//创建右子树
(tree->rchild);
createBTtree}
else
{
= nullptr;
tree }
}
/**
* @brief 遍历中序线索二叉树
*
* @param tree
*/
void printInOrderThread(BTtree &tree)
{
= tree; // now为当前节点
BTtree now while (now)
{
//找到最左节点,最左节点为第一个线索节点
while (now->ltag == LINKCHILD)
{
= now->lchild;
now }
//输出节点信息
<< now->data << endl;
cout //如果右孩子为线索,则线索下去
while (now->rtag == LINKOTHER && now->rchild)
{
= now->rchild; //去往后驱节点
now << now->data << endl;
cout }
= now->rchild;
now }
}
int main(int argc, char **argv)
{
;
BTtree tree(tree);
createBTtree(tree);
createInThread(tree);
printInOrderThread<< "end" << endl;
cout return 0;
}
/*
input data
2
input data
1
input data
-1
input data
-1
input data
3
input data
-1
input data
-1
1
2
3
end
*/
//等待填坑
//等待填坑