線索二叉樹:
對於一個有n個結點的二叉鏈表,每個結點有指向左右孩子的兩個指針域,所以一共是2n個指針域。而n個結點的二叉樹一共有n-1條分支線,也就是說存在n+1個空指針域。
我們可以考慮利用那些空地址,存放指向結點在某種遍歷次序下的前驅和後繼結點的地址。
我們把這種指向前驅和後繼的指針稱爲線索,加上線索的二叉鏈表稱爲線索鏈表,相應的二叉樹就稱爲線索二叉樹。
我們對二叉樹以某種次序遍歷使其變爲線索二叉樹的過程稱作是線索化。線索化的過程就是在遍歷的過程修改空指針的過程。
其實線索二叉樹,等於把一棵二叉樹轉變成了一個雙向鏈表。
線索二叉樹結構實現:
typedef enum {Link, Thread} PointerTag;
typedef struct BiThrNode
{
TElemType data;
struct BiThrNode *lchild, *rchild;
PointerTag LTag;
PointerTag RTag;
} BiThrNode, *BiThrTree;
BiThrTree pre;
void InThreading(BiThrTree p)
{
if (p)
{
InThreading(p->lchild);
if (!p->lchild)
{
p->LTag = Thread;
p->lchild = pre;
}
if (!pre->rchild)
{
pre->RTag = Thread;
pre->rchild = p;
}
pre = p;
InThreading(p->rchild);
}
}
遍歷線索二叉樹:
在二叉樹線索鏈表上添加一個頭結點,並令其lchild域的指針指向二叉樹的根結點,其rchild域的指針指向中序遍歷訪問的最後一個結點。反之,令二叉樹的中序序列中的第一個結點中,lchild域指針和最後一個階段的rchild域指針均指向頭結點。這樣定義的好處就是我們既可以從第一個結點其順後繼進行遍歷,也可以從最後一個結點起順前驅進行遍歷。
Status InOrderTraverse_Thr(BiThrTree T)
{
BiThrTree p;
p = T->lchild;
while (p != T)
{
while (p->LTag == Link)
p = p->lchild;
printf("%c", p->data);
while (p->RTag == Thread && p->rchild != T)
{
p = p->rchild;
printf("%c", p->data);
}
p = p->rchild;
}
return OK;
}
它等於是一個鏈表的掃描,所以時間複雜度爲O(n)。