* Retranslate the complete Japanese online edition from Chinese * Fit Japanese homepage labels and localize heading permalinks * Point Japanese contribution instructions to the Japanese preview * Replace locale conditionals with multilingual UI tables
5.3 KiB
まとめ
要点の振り返り
- 二分木は「一つを二つに分ける」という分割統治の論理を表す非線形データ構造です。各ノードには値と、左右の子をそれぞれ指す二つのポインタがあります。
- あるノードの左(右)の子とその下のノードが作る木を、そのノードの左(右)部分木と呼びます。
- 関連する用語には、根ノード、葉ノード、レベル、次数、辺、高さ、深さなどがあります。
- 初期化、ノードの挿入・削除の方法は、連結リストと似ています。
- 主な種類には、パーフェクト二分木、完全二分木、全二分木、平衡二分木があります。パーフェクト二分木は最も理想的な状態で、連結リストは退化した最悪の状態です。
- 二分木は配列でも表せます。ノードの値と空の位置をレベル順に並べ、親子のインデックスの対応でポインタを実現します。
- レベル順走査は幅優先探索の一種で、一周ずつ外へ広がるように層ごとに進み、通常はキューで実装します。
- 行きがけ順、通りがけ順、帰りがけ順は深さ優先探索で、行き止まりまで進んでから戻って続ける方法です。通常は再帰で実装します。
- 二分探索木は要素を効率よく探せるデータ構造で、探索、挿入、削除の時間計算量はすべて
O(\log n)です。連結リストに退化すると、いずれもO(n)に悪化します。 - AVL 木は平衡二分探索木とも呼ばれ、回転によって、挿入と削除を続けても平衡を保ちます。
- AVL 木の回転には、右回転、左回転、右回転してから左回転、左回転してから右回転があります。挿入や削除の後、下から上へ回転して平衡を取り戻します。
Q & A
Q:ノードが一つだけの二分木では、木の高さも根の深さも 0 ですか?
はい。通常は、通る辺の数で高さと深さを定義するためです。
Q:二分木の挿入・削除は複数の操作を組み合わせるとありますが、どういう意味ですか? リソースの子ノードのリソースを解放することと考えてよいですか?
二分探索木を例にすると、削除には三つの場合があり、それぞれで複数のノード操作が必要です。
Q:二分木の DFS には、なぜ行きがけ順、通りがけ順、帰りがけ順があり、それぞれ何に使いますか?
配列を順方向や逆方向に走査するのと同様、これらは特定の順序で結果を得るための三つの走査方法です。例えば二分探索木では、左の子の値 < 根の値 < 右の子の値 が成り立つため、「左 \rightarrow 根 \rightarrow 右」の順で走査すれば、整列済みのノード列を得られます。
Q:右回転は不均衡な node、child、grand_child の関係を処理しますが、node と親のつながりは更新しなくてよいのですか? 切れてしまいませんか?
再帰の視点から考える必要があります。right_rotate(root) は部分木の根を受け取り、最後に return child で回転後の根を返します。部分木の根と親の接続は、この関数から戻った後に行うので、右回転の処理範囲には含まれません。
Q:C++ で関数を private と public に分ける基準は何ですか? height() は public、updateHeight() は private なのはなぜですか?
主に利用範囲で決めます。クラス内部だけで使うなら private にします。例えば updateHeight() は挿入や削除の一段階なので、利用者が単独で呼ぶ意味はありません。一方、height() は vector.size() のように高さを取得するものなので、使えるように public にします。
Q:入力データから二分探索木をどう構築しますか? 根の選び方は重要ですか?
はい。構築方法は、二分探索木のコードの build_tree() にあります。通常、入力をソートして中点の要素を根とし、左右の部分木を再帰的に構築します。こうすることで、平衡性をできるだけ高く保てます。
Q:Java の文字列比較には、必ず equals() を使いますか?
Java では、基本データ型の == は二つの変数の値が等しいかを比較します。参照型では、二つの方法の仕組みが異なります。
==:二つの変数が同じオブジェクト、つまり同じメモリ位置を指すかを比較します。equals():二つのオブジェクトの値が等しいかを比較します。
値を比較するなら equals() を使うべきです。ただし、String a = "hi"; String b = "hi"; で初期化した文字列は文字列定数プールに格納され、同じオブジェクトを指すため、a == b でも内容を比較できます。
Q:幅優先走査で最下層に到達する直前、キューのノード数は 2^h ですか?
はい。例えば高さ h = 2 のパーフェクト二分木なら、総ノード数は n = 7 で、最下層のノード数は 4 = 2^h = (n + 1) / 2 です。