C++で学ぶ二分木のレベル順トラバーサル(幅優先探索)の実装方法
二分木が与えられたとき、それをレベル順トラバーサル(Level Order Traversal)、いわゆる幅優先探索(BFS)の手法で走査することを考えます。
例えば、次のような二分木があるとします。

この木に対してレベル順トラバーサルを行うと、ノードは上の階層から左から右へと順番に訪問され、結果は以下のようになります。
[10, 5, 16, 8, 15, 20, 23]
アルゴリズムの手順
この問題を解くためには、キュー(queue)を利用します。手順は以下の通りです。
- ノードを格納するためのキュー
queを定義します - ルートノードをキューに挿入します
- キューが空になるまで、以下の処理を繰り返します
- キューの先頭にある要素を取り出します
- その要素の値を出力します
- 左の子が存在する場合は、左の子をキューに挿入します
- 右の子が存在する場合は、右の子をキューに挿入します
- キューの先頭要素を削除します
キューを使うことで、同じ階層のノードを左から右の順序で処理でき、これがまさにレベル順トラバーサルの動作となります。
C++での実装例
それでは、実際のC++コードを見てみましょう。
#include<iostream>
#include<queue>
using namespace std;
class node{
public:
int h_left, h_right, bf, value;
node *left, *right;
};
class tree{
private:
node *get_node(int key);
public:
node *root;
tree(){
root = NULL; // 最初はルートをNULLに設定
}
void levelorder_traversal(node *r);
node *insert_node(node *root, int key);
};
node *tree::get_node(int key){
node *new_node;
new_node = new node; // 新しいノードを動的に生成
new_node->h_left = 0; new_node->h_right = 0;
new_node->bf = 0;
new_node->value = key; // 与えられたキーの値を格納
new_node->left = NULL; new_node->right = NULL;
return new_node;
}
void tree::levelorder_traversal(node *root){
queue <node*> que;
node *item;
que.push(root); // 最初にルートを挿入
while(!que.empty()){
item = que.front(); // 先頭から要素を取得
cout << item->value << " ";
if(item->left != NULL) // 左の子が存在すればキューに挿入
que.push(item->left);
if(item->right != NULL) // 右の子が存在すればキューに挿入
que.push(item->right);
que.pop(); // キューから要素を削除
}
}
node *tree::insert_node(node *root, int key){
if(root == NULL){
return (get_node(key)); // 木が空の場合、新しいノードをルートとして生成
}
if(key < root->value){ // キーがルートの値より小さい場合は左へ
root->left = insert_node(root->left, key);
}
else if(key > root->value){ // キーがルートの値より大きい場合は右へ
root->right = insert_node(root->right, key);
}
return root; // 同じキーが既に存在する場合は再度挿入しない
}
main(){
node *root;
tree my_tree;
// 木にいくつかのキーを挿入
my_tree.root = my_tree.insert_node(my_tree.root, 10);
my_tree.root = my_tree.insert_node(my_tree.root, 5);
my_tree.root = my_tree.insert_node(my_tree.root, 16);
my_tree.root = my_tree.insert_node(my_tree.root, 20);
my_tree.root = my_tree.insert_node(my_tree.root, 15);
my_tree.root = my_tree.insert_node(my_tree.root, 8);
my_tree.root = my_tree.insert_node(my_tree.root, 23);
cout << "Level-Order Traversal: ";
my_tree.levelorder_traversal(my_tree.root);
}入力
[10,5,16,null,8,15,20,null,null,null,null,null,null,null,23]
出力
Level-Order Traversal: 10 5 16 8 15 20 23
まとめ
レベル順トラバーサルは、再帰ではなくキューというデータ構造を活用する点が特徴的です。深さ優先探索(DFS)がスタックや再帰を用いるのに対し、幅優先探索では各階層を順番に処理できるため、木の最小の深さを求める問題や、階層ごとの処理が必要な場面で特に有効です。計算量はノード数を N とすると O(N)、必要なメモリは最悪の場合 O(N) となります。
-
【データ構造】二分探索木のレベル順走査(Level-Order Traversal)をC++で実装して理解しよう
本記事では、二分探索木(Binary Search Tree)におけるレベル順走査(Level-Order Traversal)の手法について詳しく解説します。レベル順走査は、木の根(ルート)から出発し、上の階層から下の階層へ、同じ深さのノードは左から右の順に訪問していく方法です。この走査は幅優先探索(BFS:Breadth-First Search)とも呼ばれ、木やグラフの探索において非常に重要な基本概念となっています。 例として、次のような二分探索木を考えてみましょう。 この木に対してレベル順走査を実行すると、ノードは次の順序で訪問されます。 10 → 5 → 16 → 8 → 15
-
Pythonで実装する二分木のジグザグレベル順走査(Zigzag Level Order Traversal)
二分木が与えられたとき、そのジグザグレベル順走査(Zigzag Level Order Traversal)の結果を求める問題を考えます。これは、第1レベルは左から右へ、第2レベルは右から左へ、第3レベルは再び左から右へ……というように、階層ごとに走査の向きを交互に切り替えながらノードを訪問する手法です。 例として、次のような二分木を扱います。 この木に対する走査結果は [[3], [20, 9], [15, 7]] になります。ルートの 3 を含む第1レベル、右から左へ読む第2レベル(20, 9)、そして左から右へ読む第3レベル(15, 7)という具合です。 アルゴリズムの流れ キュー