二叉樹 n 節點有 2n 指標域,n-1 條連線 → n+1 個空指標域。利用空域儲存前驅/後繼資訊,避免遍歷時需堆疊。
Ltag=1)Rtag=1)typedef struct BiThrNode {
ElemType data;
struct BiThrNode *Lchild, *Rchild;
int Ltag, Rtag; // 0=指標, 1=線索
} BiThrNode, *BiThrTree;
Rtag=1) → 右鏈直接是後繼Rtag=0) → 後繼為右子樹中最左下節點 (沿左鏈至 Ltag=1)
BiThrNode *pre; // 全域變數,指向剛訪問節點
void InThreading(BiThrNode *T) {
if (T) {
InThreading(T->Lchild);
if (!T->Lchild) { T->Ltag = 1; T->Lchild = pre; } // 前驅線索
if (!pre->Rchild) { pre->Rtag = 1; pre->Rchild = T; } // 後繼線索
pre = T;
InThreading(T->Rchild);
}
}
Status InOrderThreading(BiThrTree *Thrdhead, BiThrTree T) {
*Thrdhead = (BiThrTree)malloc(sizeof(BiThrNode));
(*Thrdhead)->Ltag = 0; (*Thrdhead)->Rtag = 1; (*Thrdhead)->Rchild = NULL;
if (!T) (*Thrdhead)->Lchild = *Thrdhead;
else {
(*Thrdhead)->Lchild = T;
pre = *Thrdhead;
InThreading(T);
pre->Rchild = *Thrdhead; pre->Rtag = 1; // 最後節點線索化
(*Thrdhead)->Rchild = pre;
}
return OK;
}
Status InOrderTraverse_Thr(BiThrTree T) {
BiThrTree p = T->Lchild; // 指向根
while (p != T) {
while (p->Ltag == 0) p = p->Lchild; // 找最左
visit(p->data);
while (p->Rtag == 1 && p->Rchild != T) {
p = p->Rchild; visit(p->data); // 走線索訪問後繼
}
p = p->Rchild; // 轉右子樹
}
return OK;
}
Status CreateBiThrTree(BiThrTree *T) {
ElemType ch; scanf("%c", &ch);
if (ch == '#') *T = NULL;
else {
*T = (BiThrTree)malloc(sizeof(BiThrNode));
(*T)->data = ch;
CreateBiThrTree(&(*T)->Lchild); if ((*T)->Lchild) (*T)->Ltag = 0;
CreateBiThrTree(&(*T)->Rchild); if ((*T)->Rchild) (*T)->Rtag = 0;
}
return OK;
}