王道-考研-数据结构-线索二叉树
7. 线索二叉树
7.1. 线索二叉树的概念
线索化:
- 若无左子树,则将左指针指向其前驱结点;
- 若无右子树,则将右指针指向其后继结点。
- 先序遍历:\(124536\)
- 中序遍历:\(425163\)
- 后序遍历:\(452631\)
线索二叉树的结点结构
ltag | lchild | data | rclild | rtag |
---|
\[标志域l(r)tag=
\begin{cases}
0,l(r)child域指示结点的左(右)孩子\\
1,l(r)child域指示结点的前驱(后继)
\end{cases}
\]
typedef struct ThreadNode
{
ElemType data;
struct ThreadNode *lchild, *rclild;
int ltag, rtag;
}ThreadNode, *ThreadTree;
这种结点结构构成的二叉链表作为二叉树的存储结构,称为线索链表。
线索二叉树的构造
常用的是中序线索二叉树。
寻找前驱结点:
- 若左指针为线索,则其指向结点为前驱结点。
- 若左指针为左孩子,则其左子树的最右侧结点为前驱结点。
寻找后继结点:
- 若右指针为线索,则其指向结点为后继结点。
- 若右指针为右孩子,则其右子树的最左侧结点为后继结点。
中序线索二叉树线索化
// p 为线索二叉树的根结点
// pre 为对应结点的前驱结点
void InThread(ThreadTree &p, ThreadTree &pre)
{
if (p != NULL)
{
InThread(p->lchild, pre);
if (p->lchild == NULL)
{
p->lchild = pre;
p->ltag = 1;
}
if (pre != NULL && pre->lchild == NULL)
{
p->rchild = p;
p->rtag = 1;
}
InThread(p->rchild, pre);
}
}
void CreateInThread(ThreadTree T)
{
ThreadTree pre = NULL;
if (T != NULL)
{
InThread(T, pre);
pre->rchild = NULL;
pre->rtag = 1;
}
}
// p 为线索二叉树的根结点
ThreadNode *FirstNode(ThreadNode *p)
{
while (p->ltag == 0)
{
p = p->lchild;
}
return p;
}
// p 为结点
ThreadNode *NextNode(ThreadNode *p)
{
if (p->rtag == 0)
{
return FirstNode(p.rchild); // 如果有孩子结点,则后继结点就是右子树最左侧的结点
}
else
{
return p.rchild;
}
}
// 遍历
void InOrder(ThreadNode *T)
{
for (ThreadNode *p = FirstNode(T); p != NULL; p = NextNode(p))
{
visit(p);
}
}
本文来自博客园,作者:咸瑜,转载请注明原文链接:https://www.cnblogs.com/bi-hu/p/16720896.html