树的递归遍历
void pre(Node head) { // 先序
if (head == null) return;
printf("%c ", head.element);
pre(head.left);
pre(head.right);
}
void in(Node head) { // 中序
if (head == null) return;
in(head.left);
printf("%c ", head.element);
in(head.right);
}
void post(Node head) { // 后序
if (head == null) return;
post(head.left);
post(head.right);
printf("%c ", head.element);
}
先序遍历:头 -> 左 -> 右,先序序列:A B D E C F G
中序遍历:左 -> 头 -> 右,中序序列:D B E A F C G
后序遍历:左 -> 右 -> 头,后序序列:D E B F G C A
背到烂的代码,背到烂的递归调用顺序,然而手动模拟仍然老出错
递归序
// 抽象,抽象,不断抽象。总结规律
void f(Node head) { // 先序?中序?后序
if (head == null) return;
printf("%c ", head.element); // 1. 打印,先序
f(head.left);
printf("%c ", head.element); // 2. 打印,中序
f(head.right);
printf("%c ", head.element); // 3. 打印,后序
}
上述代码运行,递归序列:A B D D D B E E E B A C F F F C G G G C A
观察
先序遍历:第一次经过时打印,先序序列:A B D E C F G
中序遍历:第二次经过时打印,中序序列:D B E A F C G
后序遍历:第三次经过时打印,后序序列:D E B F G C A
为什么?
为什么先序遍历中某个节点左边与后序遍历中该节点右边的交集是这个节点的祖先节点?
举例
左图以 F 为例,递归序:A B D D D B E E E B A C F F H H H F C G G G C A
先序:A B D E C F H G;后序:D E B H F G C A
A B D E C 与 G C A 交为 A C 是 F 的祖先
右图以 E 为例,递归序:A B D D D B E H H H E E B A C F F F C G G G C A
先序:A B D E H C F G;后序:D H E B F G C A
A B D 与 B F G C A 交为 A B 是 E 的祖先
观察
- 先序遍历:一定会打印根节点左子树,该节点的祖宗
- 后序遍历:一定不打印根节点右子树,该节点的祖宗
- 所以两者交集只有该节点的祖宗
为什么会会产生这种现象?回头看一下递归序
因为先序遍历第一次就会打印,后序遍历要到第三次才打印