二分木の二重順走査(ダブルオーダー走査)を実装するC++プログラム
本記事では、二分探索木(BST)における二重順走査(Double Order Traversal)を実装するC++プログラムを紹介します。
二重順走査とは、各部分木の根ノードを2回訪問する走査手法です。通常の行きがけ順・通りがけ順・帰りがけ順とは異なり、左部分木を辿る前後で根を再度出力する点が特徴です。
アルゴリズム
プログラムは以下の手順で動作します。
Begin
クラス BST は以下の関数を持つ:
insert() = 木に要素を挿入する:
根ノードを設定する。
ノードの値が根より大きければ右の子として、
そうでなければ左の子として挿入する。
doubleOrder() = 二重順走査を実行する:
root == null の場合
「木は空です」と表示する。
それ以外の場合、以下を実行する:
(部分)木の根を訪問する。
左部分木を訪問する。
再び(部分)木の根を訪問する。
右部分木を訪問する。
Endサンプルコード
# include <iostream>
# include <cstdlib>
using namespace std;
struct nod // ノードの宣言 {
int info;
struct nod *l;
struct nod *r;
}*r;
class BST {
public:// 関数の宣言
void insert(nod *, nod *);
void doubleOrder(nod *);
void show(nod *, int);
BST() {
r = NULL;
}
};
void BST::insert(nod *tree, nod *newnode) {
if (r == NULL) {
r = new nod;
r->info = newnode->info;
r->l = NULL;
r->r = NULL;
cout<<"Root Node is Added"<<endl;
return;
}
if (tree->info == newnode->info) {
cout<<"Element already in the tree"<<endl;
return;
}
if (tree->info >newnode->info) {
if (tree->l != NULL) {
insert(tree->l, newnode);
} else {
tree->l= newnode;
(tree->l)->l = NULL;
(tree->l)->r= NULL;
cout<<"Node Added To Left"<<endl;
return;
}
} else {
if (tree->r != NULL) {
insert(tree->r, newnode);
} else {
tree->r = newnode;
(tree->r)->l= NULL;
(tree->r)->r = NULL;
cout<<"Node Added To Right"<<endl;
return;
}
}
}
void BST::doubleOrder(nod *ptr) {
if (r == NULL) {
cout << "Tree is empty" << endl;
return;
}
if (ptr != NULL) {
cout << ptr->info << " ";
doubleOrder(ptr->l);
cout << ptr->info << " ";
doubleOrder(ptr->r);
}
}
void BST::show(nod *ptr, int level)// 木を表示する {
int i;
if (ptr != NULL) {
show(ptr->r, level + 1);
cout << endl;
if (ptr == r)
cout << "Root->: ";
else {
for (i = 0; i < level; i++)
cout << " ";
}
cout << ptr->info;
show(ptr->l, level + 1);
}
}
int main() {
int c, n;
BST bst;
nod *t;
while (1)// switch文によるメニュー処理 {
cout << "1.Insert Element " << endl;
cout << "2.Double-Order Traversal" << endl;
cout << "3.Show" << endl;
cout << "4.Quit" << endl;
cout << "Enter your choice : ";
cin >>c;
switch (c)// switch文による分岐処理 {
case 1:
t = new nod;
cout << "Enter the number to be inserted : ";
cin >>t->info;
bst.insert(r, t);
break;
case 2:
cout << "Double-Order Traversal of BST:" << endl;
bst.doubleOrder(r);
cout << endl;
break;
case 3:
cout << "Print BST:" << endl;
bst.show(r, 1);
cout << endl;
break;
case 4:
exit(1);
default:
cout << "Wrong choice" << endl;
}
}
}実行結果
以下は、値 7, 6, 4, 2, 10 をこの順に挿入し、木の表示と二重順走査を実行した際の出力例です。
1.Insert Element 2.Double-Order Traversal 3.Show 4.Quit Enter your choice : 1 Enter the number to be inserted : 7 Root Node is Added 1.Insert Element 2.Double-Order Traversal 3.Show 4.Quit Enter your choice : 1 Enter the number to be inserted : 6 Node Added To Left 1.Insert Element 2.Double-Order Traversal 3.Show 4.Quit Enter your choice : 1 Enter the number to be inserted : 4 Node Added To Left 1.Insert Element 2.Double-Order Traversal 3.Show 4.Quit Enter your choice : 1 Enter the number to be inserted : 2 Node Added To Left 1.Insert Element 2.Double-Order Traversal 3.Show 4.Quit Enter your choice : 1 Enter the number to be inserted : 10 Node Added To Right 1.Insert Element 2.Double-Order Traversal 3.Show 4.Quit Enter your choice : 3 Print BST: 10 Root->: 7 6 4 2 1.Insert Element 2.Double-Order Traversal 3.Show 4.Quit Enter your choice : 2 Double-Order Traversal of BST: 7 6 4 2 2 4 6 7 10 10 1.Insert Element 2.Double-Order Traversal 3.Show 4.Quit Enter your choice : 4
解説のポイント
- insert():BSTの性質に従い、挿入する値が現在のノードより小さければ左部分木へ、大きければ右部分木へ再帰的に進みます。重複する値は登録されません。
- doubleOrder():根を出力 → 左部分木を走査 → 再び根を出力 → 右部分木を走査、という順序で再帰的に処理します。そのため出力例では
7 6 4 2 2 4 6 7 10 10のように、各ノードの値が2回ずつ現れます。 - show():木の構造をインデント付きで視覚的に表示する補助関数です。
このように二重順走査は、木構造の前後関係を強調したい場合や、特定のアルゴリズムの学習・デバッグ時に役立つ走査方法です。
-
C++で学ぶ二分木のレベル順トラバーサル(幅優先探索)の実装方法
二分木が与えられたとき、それをレベル順トラバーサル(Level Order Traversal)、いわゆる幅優先探索(BFS)の手法で走査することを考えます。例えば、次のような二分木があるとします。この木に対してレベル順トラバーサルを行うと、ノードは上の階層から左から右へと順番に訪問され、結果は以下のようになります。[10, 5, 16, 8, 15, 20, 23]アルゴリズムの手順この問題を解くためには、キュー(queue)を利用します。手順は以下の通りです。ノードを格納するためのキュー que を定義しますルートノードをキューに挿入しますキューが空になるまで、以下の処理を繰り返しますキュ
-
C++でAVL木(AVLツリー)を実装する方法:回転操作とサンプルコードを徹底解説
AVL木とは AVL木(AVL Tree)は、自己平衡型二分探索木(Self-balancing Binary Search Tree)の一種です。すべてのノードにおいて、左部分木と右部分木の高さの差が「1以下」に保たれるという性質を持っています。この平衡条件により、木が片側に偏って成長することを防ぎ、検索・挿入・削除といった操作を常に効率的(O(log n))に行うことができます。 木の回転(Tree Rotation)とは 木の回転とは、要素の順序(ソート順)を崩すことなく木の構造を変更する操作のことです。あるノードを一段上へ移動させ、別のノードを一段下へ移動させることで実現されます。 回