4.7 KiB
二分木の走査
物理構造の観点から見ると、木は連結リストを基盤としたデータ構造であり、その走査はポインタを通じてノードへ順にアクセスすることで行われます。しかし、木は非線形データ構造であるため、木の走査は連結リストの走査よりも複雑であり、検索アルゴリズムを用いて実現する必要があります。
二分木の一般的な走査方法には、レベル順走査、先行順走査、中間順走査、後行順走査などがあります。
レベル順走査
次の図に示すように、レベル順走査(level-order traversal)では、二分木を上から下へ層ごとに走査し、各層では左から右の順にノードへアクセスします。
レベル順走査は本質的に幅優先走査(breadth-first traversal)に属し、幅優先探索(breadth-first search, BFS)とも呼ばれます。これは「同心円状に外側へ広がる」ような、層ごとの走査方法を表しています。
コードの実装
幅優先走査は通常「キュー」を用いて実装します。キューは「先入れ先出し」の規則に従い、幅優先走査は「層ごとに進む」という規則に従います。両者の背後にある考え方は一致しています。実装コードは次のとおりです:
[file]{binary_tree_bfs}-[class]{}-[func]{level_order}
計算量
- 時間計算量は $O(n)$ :すべてのノードを1回ずつ訪問するため、計算量は
O(n)です。ここで、nはノード数です。 - 空間計算量は $O(n)$ :最悪の場合、すなわち完全二分木では、最下層に到達する前に、キュー内には最大で同時に
(n + 1) / 2個のノードが存在し、O(n)の空間を使用します。
先行順・中間順・後行順走査
同様に、先行順・中間順・後行順走査はいずれも深度優先走査(depth-first traversal)に属し、深度優先探索(depth-first search, DFS)とも呼ばれます。これは「まず行き止まりまで進み、その後で戻って続ける」という走査方法を表しています。
次の図は、二分木に対して深度優先走査を行う仕組みを示しています。深度優先走査は、二分木全体の外周をぐるりと「一周する」ようなものです。各ノードでは3つの位置に出会い、それぞれが先行順走査・中間順走査・後行順走査に対応します。
コードの実装
深度優先探索は通常、再帰に基づいて実装されます:
[file]{binary_tree_dfs}-[class]{}-[func]{post_order}
!!! tip
深度優先探索は反復によって実装することもできます。興味のある読者は自身で調べてみてください。
次の図は、二分木の先行順走査における再帰の過程を示しており、「行き」と「帰り」という2つの逆向きの部分に分けられます。
- 「行き」は新しいメソッドの開始を表し、この過程でプログラムは次のノードにアクセスします。
- 「帰り」は関数の復帰を表し、現在のノードへのアクセスが完了したことを意味します。
計算量
- 時間計算量は $O(n)$ :すべてのノードを1回ずつ訪問するため、計算量は
O(n)です。 - 空間計算量は $O(n)$ :最悪の場合、すなわち木が連結リストに退化したとき、再帰の深さは
nに達し、システムはO(n)のスタックフレーム空間を使用します。












