Oli は、順序通りのトラバーサルが O(n) であることは正しいですが、一般的な後続/先行ルーチンを使用するとアルゴリズムの複雑さが増すことは正しいです。そう:
簡単な解決策は、順序通りのトラバーサルを使用してツリーをたどり、最後に右向きのエッジを取得したとき (たとえば、last_right_ancestor_seenという変数を使用してその親ノードを指す) と最後のリーフ ノードを追跡することです。 (たとえば、last_leaf_seen (実際には、適切な子を持たないノード) で見たことがあります)。葉ノードを処理するたびに、その前身はlast_right_ancestorであり、非葉ノードにヒットするたびに、その前身はlast_leaf_seen です。 O(n) 時間、O(1) スペースの 2 つを出力するだけです。
十分に明確であることを願っています。そうでない場合は、図を描くことができます。
編集:これはテストされていませんが、おそらく正しいです:
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;
}
}