C++で二分木における親子ノード合計の最大値を求める方法
このチュートリアルでは、二分木(Binary Tree)において「親ノードとその子ノード2つの値の合計」を計算し、その中で最大となる値を見つけるプログラムについて解説します。
具体的には、二分木が与えられたとき、左右両方の子を持つ各ノードについて「親ノード+左の子+右の子」の合計を求め、全ノードの中で最も大きい合計値を出力するのが目的です。
アルゴリズムの考え方
この問題は、木を再帰的に走査することで効率よく解くことができます。手順は以下の通りです。
- 現在のノードがNULLの場合は0を返します。
- 左部分木に対して再帰的に同じ処理を行い、結果を保持します。
- 現在のノードが左の子と右の子の両方を持つ場合のみ、「親+左の子+右の子」の合計を計算します。
- これまでの最大値と比較して、より大きい方を記録します。
- 右部分木に対しても再帰的に処理を行い、最終的な最大値を返します。
なお、子が1つしかないノードや葉ノードは計算対象外となる点に注意してください。このアルゴリズムの計算量はO(n)で、木の全ノードを一度ずつ訪問するだけで済みます。
実装例(C++)
#include <iostream>
using namespace std;
struct Node {
int data;
struct Node *left, *right;
};
// ノードの生成
struct Node* newNode(int n) {
struct Node* root = new Node();
root->data = n;
root->left = root->right = NULL;
return root;
}
int maxSum(struct Node* root) {
if (root == NULL)
return 0;
int res = maxSum(root->left);
if (root->left != NULL && root->right != NULL) {
int sum = root->data + root->left->data + root->right->data;
res = max(res, sum);
}
return max(res, maxSum(root->right));
}
int main() {
struct Node* root = newNode(15);
root->left = newNode(16);
root->left->left = newNode(8);
root->left->left->left = newNode(55);
root->left->right = newNode(67);
root->left->right->left = newNode(44);
root->right = newNode(17);
root->right->left = newNode(7);
root->right->left->right = newNode(11);
root->right->right = newNode(41);
cout << maxSum(root);
return 0;
}
出力結果
91
動作の解説
上記の例では、ノード15・16・17など複数の親子関係が存在します。それぞれの親ノードについて合計を計算すると、例えば以下のようになります。
- ノード15:15 + 16 + 17 = 48
- ノード16:16 + 8 + 67 = 91
- ノード17:17 + 7 + 41 = 65
この中で最も大きいのは91であるため、プログラムは91を出力します。このように再帰的な深さ優先探索を用いることで、簡潔かつ効率的に親子ノード合計の最大値を求めることができます。
-
C++で二分木の最大垂直和を求める方法
はじめに二分木が与えられたとき、垂直順序走査における各垂直列のノード値の合計を計算し、その中から最大値を求めて出力するのが本記事の課題です。例として、以下のような二分木を考えてみましょう。この二分木を垂直順序走査すると、各列の合計は次のようになります。4 2 1 + 5 + 6 = 12 3 + 8 = 11 7 9各列の合計の中で最大となるのは 12 です。アルゴリズムの考え方アプローチはシンプルです。幅優先探索(BFS)を用いて垂直順序走査を行い、各ノードに水平距離を割り当てます。ルートの水平距離を 0 とし、左に移動するごとに -1、右に移動するごとに +1 とします。同じ水平距離を持つ
-
C++で二分木の子ノード合計プロパティを検証する方法
二分木が与えられたとき、次のプロパティ(性質)を満たしていれば、その二分木は有効とみなされます。各ノードのデータ値は、左の子ノードと右の子ノードの値の合計と一致していなければなりません。どちらかの側に子ノードが存在しない場合は、その値は0として扱われます。例えば、以下のような木が与えられた場合、このプロパティを満たしていることになります。この性質を確認するための特別なトリックは存在せず、木を再帰的に走査する必要があります。ノードとその両方の子がプロパティを満たしていればtrueを返し、そうでなければfalseを返します。アルゴリズムの流れ検証は以下の手順で行われます。ノードがNULL、または葉