C++で1回の走査により二分木の密度を求める方法
はじめに
このチュートリアルでは、1回の走査(トラバーサル)だけで二分木の密度を求める方法について解説します。
二分木の密度は、次の式で定義されます。
密度 = 木のサイズ ÷ 木の高さ
- 木のサイズ:与えられた二分木に含まれるノードの総数
- 木の高さ:根ノードから最も深い葉ノードまでの最大深度
アルゴリズムの手順
問題を解くための手順は以下の通りです。
- 二分木のテストデータを初期化します。
- 木のサイズと高さを同時に求めます。
- 再帰的に木の高さを計算します。
- 左右の部分木の高さを比較し、大きい方に1を加えた値を返します。
- 訪問したノードごとにサイズをインクリメントします。
- 「木のサイズ ÷ 木の高さ」という式で密度を計算します。
- 計算結果である密度を出力します。
実装例
それでは、実際のコードを見てみましょう。
#include<bits/stdc++.h>
using namespace std;
struct Node {
int data;
Node *left, *right;
};
Node* newNode(int data) {
Node* node = new Node;
node->data = data;
node->left = node->right = NULL;
return node;
}
int findHeightAndSizeOfTree(Node* node, int &size) {
if (node == NULL) {
return 0;
}
int leftTreeCount = findHeightAndSizeOfTree(node->left, size);
int rightTreeCount = findHeightAndSizeOfTree(node->right, size);
size++;
return (leftTreeCount > rightTreeCount) ? leftTreeCount + 1 : rightTreeCount + 1;
}
float treeDensity(Node* root) {
if (root == NULL) {
return 0;
}
int treeSize = 0;
int treeHeight = findHeightAndSizeOfTree(root, treeSize);
return (float)treeSize/treeHeight;
}
int main() {
Node* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
root->right->left = newNode(6);
root->right->right = newNode(7);
cout << treeDensity(root) << endl;
return 0;
}
実行結果
上記のプログラムを実行すると、以下の出力が得られます。
2.33333
このサンプルツリーはノードが7個、高さが3であるため、密度は 7 ÷ 3 ≒ 2.33333 となります。
まとめ
このチュートリアルでは、1回の走査で二分木のサイズと高さを同時に取得し、その密度を計算する方法を学びました。各ノードを一度だけ訪問するため、時間計算量はO(n)と非常に効率的です。チュートリアルの内容について質問がある場合は、コメント欄でお気軽にお知らせください。
-
【C++】二分木の中順走査(Inorder Traversal)を再帰的に実装する方法
木の走査(Tree Traversal)は、グラフ走査の一種であり、木に含まれるすべてのノードをそれぞれ一度だけ訪問(チェックまたは出力)する操作です。二分探索木における中順走査(Inorder Traversal、通りがけ順とも呼ばれます)では、「左の子 → 根 → 右の子」の順序で各ノードを訪問します。 二分木の中順走査の具体例を見てみましょう。次のような二分木が与えられたとします。 この二分木に対する中順走査の結果は次のとおりです。 中順走査の結果:1 4 5 6 8 それでは、中順走査を再帰的に実行するC++プログラムを見ていきましょう。 サンプルコード #include<i
-
二分木の先行順(プレオーダー)走査を再帰的に実行するC++プログラム
二分木の先行順走査とは木の走査(トラバーサル)はグラフ走査の一種であり、木に含まれるすべてのノードをそれぞれ一度だけ訪れて処理を行うことを指します。二分探索木における先行順走査(プレオーダー走査)では、「根 → 左部分木 → 右部分木」の順序で各ノードを訪問するのが特徴です。次のような二分木を例に考えてみましょう。この二分木に対する先行順走査の結果は 6 4 1 5 8 となります。ここからは、この先行順走査を再帰的に実行するC++プログラムを紹介します。C++による実装例#include<iostream> using namespace std; struct node {