Files
C_code/exercise/exercise/23.c
T
2025-12-16 08:14:56 +08:00

98 lines
3.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 后序线索二叉树构建(根为1
// 输入:n,随后 n 行,每行两个整数 l、r(0 表示无孩子)。
// 输出:n 行,每行四个整数:lchild(i) ltag(i) rchild(i) rtag(i)
// 规则:
// - 若有左儿子:ltag(i)=0lchild(i) 为左儿子编号;否则 ltag(i)=1,lchild(i) 为后序前驱,无前驱为 -2。
// - 若有右儿子:rtag(i)=0rchild(i) 为右儿子编号;否则 rtag(i)=1,rchild(i) 为后序后继,无后继为 -1。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n;
if (scanf("%d", &n) != 1) return 0;
if (n <= 0) return 0;
int *L = (int *)malloc((n + 1) * sizeof(int));
int *R = (int *)malloc((n + 1) * sizeof(int));
if (!L || !R) return 0;
for (int i = 1; i <= n; ++i) {
int l, r;
if (scanf("%d %d", &l, &r) != 2) {
free(L); free(R);
return 0;
}
L[i] = l; R[i] = r;
}
// 迭代后序遍历,生成访问序列 order
int *stack = (int *)malloc((n + 1) * sizeof(int));
int *order = (int *)malloc(n * sizeof(int));
if (!stack || !order) { free(L); free(R); return 0; }
int top = 0, k = 0;
int cur = 1; // 根为 1
int prev = 0; // 最近已输出的结点
while (cur || top) {
if (cur) {
stack[top++] = cur;
cur = L[cur]; // 沿左链压栈
} else {
int u = stack[top - 1];
if (R[u] && prev != R[u]) {
cur = R[u]; // 右子树存在且未处理,转向右子树
} else {
// 右子树为空或已处理,弹栈并记录该结点
--top;
order[k++] = u;
prev = u;
}
}
}
// 位置映射:pos[node] = 在后序序列中的索引
int *pos = (int *)malloc((n + 1) * sizeof(int));
if (!pos) { free(stack); free(order); free(L); free(R); return 0; }
for (int i = 1; i <= n; ++i) pos[i] = -1;
for (int i = 0; i < k; ++i) pos[order[i]] = i;
// 输出域与标记域
int *outL = (int *)malloc((n + 1) * sizeof(int));
int *ltag = (int *)malloc((n + 1) * sizeof(int));
int *outR = (int *)malloc((n + 1) * sizeof(int));
int *rtag = (int *)malloc((n + 1) * sizeof(int));
if (!outL || !ltag || !outR || !rtag) {
free(pos); free(stack); free(order); free(L); free(R);
return 0;
}
for (int i = 1; i <= n; ++i) {
if (L[i]) { // 有左儿子
ltag[i] = 0;
outL[i] = L[i];
} else { // 无左儿子,线索到后序前驱
ltag[i] = 1;
if (pos[i] > 0) outL[i] = order[pos[i] - 1];
else outL[i] = -2; // 无前驱
}
if (R[i]) { // 有右儿子
rtag[i] = 0;
outR[i] = R[i];
} else { // 无右儿子,线索到后序后继
rtag[i] = 1;
if (pos[i] >= 0 && pos[i] < k - 1) outR[i] = order[pos[i] + 1];
else outR[i] = -1; // 无后继
}
}
for (int i = 1; i <= n; ++i) {
printf("%d %d %d %d\n", outL[i], ltag[i], outR[i], rtag[i]);
}
free(outL); free(ltag); free(outR); free(rtag);
free(pos); free(stack); free(order);
free(L); free(R);
return 0;
}