Oli 是正确的,中序遍历是 O(n),但你是对的,使用一般的后继/前继例程会增加算法的复杂性。所以:
一个简单的解决方案是使用按序遍历来遍历树,跟踪您最后一次被带入右指向边(例如,使用名为last_right_ancestor_seen的变量指向其父节点)和最后一个叶节点你已经看到了(比如说,在last_leaf_seen中(实际上是任何没有右子节点的节点)。每次处理叶节点时,它的前身是last_right_ancestor,每次遇到非叶节点时,它的前身是last_leaf_seen,并且你只需打印两个。O(n) 时间,O(1) 空间。
希望它足够清楚,如果没有,我可以给你画一个图表。
编辑:这是未经测试的,但可能是正确的:
walk(node* current, node* last_right_ancestor_seen, node* last_leaf_seen) {
if(current->left != null) {
walk(current->left, last_right_ancestor_seen, last_leaf_seen);
}
if(current->is_leaf()) {
if(last_right_ancestor_seen != null)
print(last_right_ancestor_seen->value, current->value);
}
else {
print(last_leaf_seen->value, current->value);
}
if(current->right != null) {
*last_right_ancestor_seen = *current;
walk(current->right, last_right_ancestor_seen, last_leaf_seen);
}
else {
*last_leaf_seen = *current;
}
}