线索二叉树
由于具有 N N N个节点的二叉查找树有 N + 1 N+1 N+1的 N U L L NULL NULL指针,因此在二叉查找树中指定给指针信息的空间的一半被浪费了。
若一个节点有一个 N U L L NULL NULL左孩子,我们使它的左儿子指向它的中缀前驱(inorder predecessor),若一个节点有一个 N U L L NULL NULL右孩子,我们让它的右儿子指向它的中缀后继(inorder successor)。这就叫做线索二叉树(threaded tree),而附加的指针就叫做线索(thread)。
- 为使从实际的儿子指针中区分出线索,需要在每个节点增加一个成员,用以标志指针是线索还是孩子。
typedef enum
{
Linked, // 表示正常孩子
Thread // 表示线索
} PointerTag;
typedef int ElementType;
struct ThreadTree;
typedef struct ThreadTree *Tree;
typedef struct ThreadTree *Position;
struct ThreadTree
{
ElementType Element;
Tree Left;
Tree Right;
PointerTag LTag;
PointerTag RTag;
};
算法实现
线索二叉树的线索算法
/**
* 以结点 p 为根的子树中序线索化
* 1. 如果 p 非空,左子树递归线索化
* 2. 如果 p 的左孩子为空,则给 p 加上左线索,将其 Ltag 置为 1,让 p 的左孩子指针指向 pre(前驱);否则将 p 的 LTag 置为 0 。
* 3. 如果 pre 的右孩子为空,则给 pre 加上右线索,将其 RTag 置为 1,让 pre 的右孩子指针指向 p(后继);否则将 pre 的 RTag 置为 0 。
* 4. 将 pre 指向刚访问过的结点 p,即 pre = p 。
* 5. 右子树递归线索化。
* */
void InThreading(Tree p)
{
// pre 是全局变量,初始化时右孩子指针为空,便于在树的最左点开始建立线索
if (p != NULL)
{
InThreading(p->Left);
if (p->Left == NULL)
{
p->LTag = Thread;
p->Left = pre;