王道-考研-数据结构-线索二叉树

7. 线索二叉树

7.1. 线索二叉树的概念

线索化:

  1. 若无左子树,则将左指针指向其前驱结点;
  2. 若无右子树,则将右指针指向其后继结点。

image

  • 先序遍历:\(124536\)

image

  • 中序遍历:\(425163\)

image

  • 后序遍历:\(452631\)

image

线索二叉树的结点结构

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;
}
}

image

image

// 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);
}
}
posted @ 2022-09-22 21:14  咸瑜  阅读(151)  评论(0编辑  收藏  举报