线索二叉树
将指向空的指针加以利用,空左子树指针指向该节点直接前驱,空右子树指针指向该节点直接后继,通过线索可以加快遍历速度
结构定义:
enum PointerTag { Link = 0, Thread = 1 };
template <typename ElemType>
struct BiThrNode
{
ElemType data;
BiThrNode* lchild, * rchild;
PointerTag LTag, RTag;
};
template<typename ElemType>
using BiThrTree = BiThrNode<ElemType>*;
基本操作:
遍历:通过线索进行中序遍历,空右子树指针直接指向直接后继,通过指针可以快速找到下一个节点
template<typename ElemType>
Status inOrderTraverse_thr(BiThrTree<ElemType>& T, Status(*visit)(BiThrTree<ElemType>&))//中序遍历线索二叉树
{
BiThrNode<ElemType>* head = T;//头节点
T = T->lchild;//树根
while (T != head)//当前节点不是头节点
{
while (T->LTag == Link)//找到中序遍历第一个节点,即最左边的节点
T = T->lchild;
visit(T);//访问该节点
while (T->RTag == Thread && T->rchild != head)//该节点无右子树,直接通过右儿子找到直接后继节点并访问
{
T = T->rchild;
visit(T);
}
T = T->rchild;//该节点有右子树,因为是中序,访问到该节点就表明已经访问过该节点的左子树了,所以开始访问该节点的右子树
}
return OK;
}
创建线索二叉树:首先创建一个头节点,头节点的左子树指针指向要创建的二叉树的根节点,然后通过递归创建二叉树
template<typename ElemType>
Status creatBiThrTree(BiThrTree<ElemType>& T, ElemType*& data)//创建线索二叉树
{
T = new BiThrNode<ElemType>;
T->lchild = NULL;
T->rchild = NULL;
_creatBiThrTree(T->lchild, data);
return OK;
}
template<typename ElemType>
Status _creatBiThrTree(BiThrTree<ElemType>& T, ElemType*& data)//创建线索二叉树
{
ElemType et;
char flag = '$';
et = *data;
if (et == flag)
T = NULL;
else
{
T = new BiThrNode<ElemType>;
T->data = et;
_creatBiThrTree(T->lchild, ++data);
_creatBiThrTree(T->rchild, ++data);
}
return OK;
}
中序线索化:首先修改头节点各个变量的值,然后开始中序线索化头节点的右子树,即二叉树;中序线索化二叉树通过递归实现,先中序线索化左子树,然后线索化根节点,最后中序线索化右子树
template<typename ElemType>
Status inOrederThreading(BiThrTree<ElemType> T)//中序线索化二叉树
{
BiThrNode<ElemType>* head = T;//先修改好头节点的各个数据
head->LTag = Link;
head->RTag = Thread;
if (!head->lchild)//如果没有左子树,即表示为空树
{
head->lchild = head;
head->rchild = head;
return ERROR;
}
_inOrderThreading(T->lchild, T);//中序线索化
T->RTag = Thread;//修改最后一个节点的各个数据
T->rchild = head;
head->rchild = T;//将头节点的右儿子指向最后一个节点
return OK;
}
template<typename ElemType>
Status _inOrderThreading(BiThrTree<ElemType>& T, BiThrNode<ElemType>*& pre)//中序线索化二叉树
{//先中序线索化左子树,在根节点,最后右子树
if (T)
{
_inOrderThreading(T->lchild, pre);//中序线索化左子树
if (T->lchild)//判断是否有左子树,修改LTag的值
T->LTag = Link;
else
{
T->LTag = Thread;
T->lchild = pre;
}
if (pre->rchild)//判断前驱是否有右子树
pre->RTag = Link;
else
{
pre->RTag = Thread;
pre->rchild = T;
}
pre = T;//当前节点改为前驱节点
_inOrderThreading(T->rchild, pre);//中序线索化右子树
}
return OK;
}
测试:
void testBiThrTree()//测试线索二叉树
{
BiThrTree<char> T;
char* data = (char*)"-*a$$b$$c$$";
cout << "创建线索二叉树" << endl;
creatBiThrTree(T, data);
inOrederThreading(T);
cout << "中序遍历:";
inOrderTraverse_thr(T,print_thr);
cout << endl;
cout << endl;
system("pause");
}
结果: