普通二叉链表中有 n+1 个空指针域,线索二叉树利用这些空指针存放遍历序列中的前驱和后继信息。
typedef struct ThreadNode {
ElemType data;
struct ThreadNode *lchild, *rchild;
int ltag, rtag; // 0:指向孩子;1:指向前驱/后继
} ThreadNode, *ThreadTree;
| 类型 | 前驱/后继依据 |
|---|---|
| 先序线索二叉树 | 先序遍历序列 |
| 中序线索二叉树 | 中序遍历序列(最常考) |
| 后序线索二叉树 | 后序遍历序列 |
ThreadTree pre = NULL; // 全局变量,记录前驱
void InThread(ThreadTree T) {
if (T != NULL) {
InThread(T->lchild); // 线索化左子树
if (T->lchild == NULL) { T->ltag = 1; T->lchild = pre; }
if (pre != NULL && pre->rchild == NULL) {
pre->rtag = 1; pre->rchild = T;
}
pre = T;
InThread(T->rchild); // 线索化右子树
}
}
void CreateInThread(ThreadTree T) {
pre = NULL;
if (T != NULL) { InThread(T); pre->rchild = NULL; pre->rtag = 1; }
}
A
/ \
B C
/ \ \
D E F
中序序列:D B E A C F
线索化后:
D: lchild→NULL(无前驱), rchild→B(后继)
B: lchild→D(前驱), rchild→E(后继)
E: lchild→B(前驱), rchild→A(后继)
A: lchild→E(前驱), rchild→C(后继)
C: lchild→A(前驱), rchild→F(后继)
F: lchild→C(前驱), rchild→NULL(无后继)
// 中序遍历第一个结点:沿左孩子到底
ThreadNode *FirstNode(ThreadNode *p){
while (p->ltag == 0) p = p->lchild;
return p;
}
// 找后继:rtag=1 直接返回;否则右子树最左下
ThreadNode *NextNode(ThreadNode *p){
if (p->rtag == 1) return p->rchild;
else return FirstNode(p->rchild);
}
// 中序遍历(无需栈)
void InOrderThread(ThreadTree T){
for (ThreadNode *p = FirstNode(T); p != NULL; p = NextNode(p)) visit(p);
}
// 找前驱:ltag=1 直接返回;否则左子树最右下
ThreadNode *PreNode(ThreadNode *p){
if (p->ltag == 1) return p->lchild;
else return LastNode(p->lchild);
}
void PreThread(ThreadTree T) {
if (T != NULL) {
if (T->lchild == NULL) { T->ltag = 1; T->lchild = pre; }
if (pre != NULL && pre->rchild == NULL) { pre->rtag = 1; pre->rchild = T; }
pre = T;
if (T->ltag == 0) PreThread(T->lchild); // 需判断 ltag 防循环
PreThread(T->rchild);
}
}
1
/ \
2 3
/ \
4 5
中序序列:4 2 5 1 3
| 结点 | ltag | lchild | rtag | rchild |
|---|---|---|---|---|
| 4 | 1 | NULL(无前驱) | 1 | 2 |
| 2 | 0 | (孩子4) | 0 | (孩子5) |
| 5 | 1 | 2 | 1 | 1 |
| 1 | 0 | (孩子2) | 0 | (孩子3) |
| 3 | 1 | 1 | 1 | NULL(无后继) |
FirstNode(1):沿左到 4,返回 4 → visit(4)
NextNode(4):rtag=1,返回 rchild=2 → visit(2)
NextNode(2):rtag=0,FirstNode(5)=5 → visit(5)
NextNode(5):rtag=1,返回 rchild=1 → visit(1)
NextNode(1):rtag=0,FirstNode(3)=3 → visit(3)
NextNode(3):rtag=1,rchild=NULL,结束
序列:4 2 5 1 3 ✓
| 操作 | 时间复杂度 |
|---|---|
| 线索化 | O(n) |
| 找前驱/后继 | O(1)(有线索)或 O(h)(无线索) |
| 遍历 | O(n) |
| 空间 | O(1)(不需要栈) |
↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。