C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で完全二分木の全ノードの合計を効率的に求める方法


問題の概要

正整数 L が与えられ、これは完全二分木(パーフェクト・バイナリツリー)のレベル数を表しているとします。この木の葉ノードには、1 から n までの番号が順に割り当てられています(n は葉ノードの総数)。また、各親ノードの値は、その 2 つの子ノードの値の合計となります。

今回の課題は、この完全二分木に含まれるすべてのノードの値の合計を出力するプログラムを作成することです。

例として、次のような木を考えてみましょう。

C++で完全二分木の全ノードの合計を効率的に求める方法

この木の場合、すべてのノードの合計は 30 になります。

解法のアプローチ

この問題を注意深く観察すると、求めるべきは全ノードの値の総和です。葉ノードには 1 から n までの連続した整数が格納されているため、等差数列の和の公式 n(n+1)/2 を使えば、葉ノードの合計を簡単に計算できます。

さらに重要な性質として、完全二分木では各レベルのノードの値の合計が必ず等しくなるという点が挙げられます。これは「親ノードの値 = 子ノード 2 つの値の合計」というルールから導かれるもので、あるレベルの合計は、その直下のレベルの合計と必ず一致します。

したがって、以下の手順で答えを求められます。

  1. 葉ノードの総数 n を 2^(L-1) で計算する(L はレベル数)
  2. 葉ノードの合計を n(n+1)/2 の公式で求める
  3. その合計にレベル数 L を掛けた値が、全ノードの合計となる

C++での実装例

#include<iostream>
#include<cmath>
using namespace std;
int treeSum(int level) {
   int total_leaves = pow(2, level - 1);   // 葉ノードの総数
   int leaf_sum = (total_leaves * (total_leaves + 1)) / 2;   // 葉ノードの合計
   int sum = leaf_sum * level;   // 各レベルの合計が等しいため、レベル数を掛ける
   return sum;
}
int main() {
   int levels = 4;
   cout << "レベル " << levels << " の完全二分木の全ノードの合計: " << treeSum(levels);
}

実行結果

レベル 4 の完全二分木の全ノードの合計: 144

計算量の評価

この解法は pow 関数と四則演算のみで構成されているため、時間計算量は O(1) です。つまり、木のサイズに関わらず一定時間で答えを求められます。実際に木を構築して全ノードを走査する方法(O(n))と比較しても、非常に効率的なアプローチだと言えるでしょう。

  1. C++で二分木の各レベルにおける非葉ノードの合計の最大値を求める方法

    この記事では、二分木が与えられたときに、すべてのレベルの中から非葉ノード(子ノードを持つノード)の合計が最大となるレベルの合計値を求めるC++プログラムの作成方法を解説します。 問題の概要 二分木の各レベルごとに非葉ノードのデータ値の合計を計算し、その中で最も大きい合計値を出力します。 入力例 出力例 9 解説 各レベルにおける非葉ノードの合計は以下のようになります。 レベル1: 4 レベル2: 1 + 2 = 3 レベル3: 9(4と7は葉ノードのため対象外) レベル4: 0 この結果から、最大の合計値は「9」であることがわかります。 解決のアプローチ この問題を解くには、二分木に対してレ

  2. C++で二分木の指定した2つのレベル間にあるすべてのノードを出力する方法

    この問題では、二分木と、木の中の2つのレベル(上位レベルと下位レベル)が与えられ、その2つのレベル間に存在するすべてのノードを出力することが求められます。二分木とは、各ノードが最大2つの子ノード(0個・1個・2個)を持つ特殊な木構造のことです。問題の例具体例を使って問題を理解しましょう。上位レベル(upper):3下位レベル(lower):1出力結果:6 3 9 7 4 8 10解決アプローチ方法1:再帰関数を使う方法この問題を解くには、指定されたレベルのノードを出力する必要があります。upperからlowerまでのレベルをループで回しながら、再帰関数を呼び出すことで実現できます。このアルゴリ