これは、同じ構造と要素という意味でのツリーの同一性の後である、元の言い回しの質問に答えます。
インオーダー (またはその他の) シーケンシャル化の比較は機能しません。異なるツリーは同じトラバーサルを持ちます。たとえば、木々
[ソース]
同じ in-order traversal を持っていますa,b,c,d,e
。2 つの(異なる) トラバーサルを使用して、それらが同じかどうかをそれぞれ確認できます。
ただし、古典的な解決策は再帰アルゴリズムです。
equal Leaf(x) Leaf(y) => x == y
| equal Node(x,l1,r1) Node(y,l2,r2) => x == y && equal(l1,l2) && equal(r1,r2)
| equal _ _ => false;
両方のツリーでツリー トラバーサルを同時に実行し、時間 Θ(n) (n はそれぞれのノード数の最大値) を要します。
更新された質問に関しては、要素ごとの同等性について順序通りのトラバーサルをチェックするだけで十分です。定義上、BST の順序通りのトラバーサルは格納された要素の並べ替えられたリストであるため、このアプローチは正しいことに注意してください。再帰的な形式では、これはアルゴリズムです:
inorder Leaf(x) = [x]
| inorder Node(x,l,r) = (inorder l) ++ [x] ++ (inorder r);
equal [] [] = true
| equal x1::r1 x2::r2 = x1 == x2 && (equal r1 r2)
| equal _ _ = false;
sameElems t1 t2 = let
e1 = inorder t1
e2 = inorder t2
in
equal e1 e2
end;
リストの連結が時間 O(1) で実行できる場合、これは時間 Θ(n) および空間 Θ(n) で実行されます。反復ソリューションは確かに優れており、おそらくより良い定数を持っています。
このチェックを o(n) 時間で実行したい場合、すべての要素を調べることさえできません。一般に、両方のツリーにはペアごとに異なる要素が含まれているため、範囲を利用することはできません。したがって、すべての一般的な要素の等価性チェックには Ω(n) の時間がかかります (より高速なアルゴリズムを想定し、失敗する 2 つのツリーを構築します)。
ただし、スペースは O(n) よりもうまく処理できます。巧妙に順番に実装する場合¹、必要な追加スペースは O(1) だけです (現在の要素へのポインター、いくつかの管理カウンター/フラグ)。
- このアルゴリズムはツリーを一時的に破棄するため、同時設定には適していないことに注意してください。