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

C++プログラム:二分木における最大独立集合(LIS)のサイズを求める方法


この記事では、与えられた二分木(バイナリツリー)における最大独立集合(LIS:Largest Independent Set)のサイズを求めるC++プログラムを紹介します。

独立集合とは、木の中で互いに隣接していない(親子関係にない)ノードだけで構成される集合のことです。つまり、「選んだノード同士が直接つながっていない」という条件のもとで、できるだけ多くのノードを選ぶ問題を解きます。

アルゴリズム

この問題は、動的計画法(メモ化再帰)を用いることで効率的に解けます。各ノードについて「そのノードを含まない場合」と「そのノードを含む場合」の2通りのサイズを計算し、大きい方を採用します。

開始。
  構造体nを作成し、データd、左の子ポインタl、右の子ポインタrを宣言する。
  2つの整数のうち大きい方を返す関数max()を定義する。
  与えられた二分木における最大独立集合のサイズを返す関数LIS()を作成する。
  現在のノードを含まない場合のサイズを計算する
  int size_excl = LIS(root->l) + LIS(root->r)
  現在のノードを含む場合のサイズを計算する
  int size_incl = 1;
  if (root->l)
    size_incl += LIS(root->l->l) + LIS(root->l->r)
  if (root->r)
    size_incl += LIS(root->r->l) + LIS(root->r->r)
  2つのサイズのうち大きい方を返す
  新しいノードを生成する関数newnode()を作成する。
終了。

最適化のポイント

各ノードには計算済みのLIS値を格納するフィールドを持たせています。一度計算した結果はキャッシュとして再利用されるため、同じ部分木を繰り返し計算する無駄がなくなり、計算量が大幅に削減されます。

サンプルコード

#include <iostream>
using namespace std;
struct n {
    int d;
    int lis;
    struct n *l, *r;
};
int max(int x, int y) {
    return (x > y) ? x : y;
}
int LIS(struct n *root) {
    if (root == NULL)
        return 0;
    if (root->lis)
        return root->lis;
    if (root->l == NULL && root->r == NULL)
        return (root->lis = 1);
        int lis_excl = LIS(root->l) + LIS(root->r);
        int lis_incl = 1;
    if (root->l)
        lis_incl += LIS(root->l->l) + LIS(root->l->r);
    if (root->r)
        lis_incl += LIS(root->r->l) + LIS(root->r->r);
        root->lis = max(lis_incl, lis_excl);
        return root->lis;
}
struct n* newnode(int d) {
    struct n* t = (struct n *) malloc(sizeof(struct n));
    t->d = d;
    t->l = t->r = NULL;
    t->lis = 0;
    return t;
}
int main() {
    struct n *root = newnode(30);
    root->l= newnode(20);
    root->l->l = newnode(10);
    root->l->r = newnode(7);
    root->l->r->l = newnode(9);
    root->l->r->r = newnode(6);
    root->r = newnode(50);
    root->r->r = newnode(26);
    cout<<"Size of the Largest Independent Set is "<< LIS(root);
    return 0;
}

実行結果

Size of the Largest Independent Set is 5

この例の二分木では、値が30・10・9・6・26である5つのノードを選ぶことで、互いに隣接しない最大の独立集合が得られます。

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

    問題の概要 正整数 L が与えられ、これは完全二分木(パーフェクト・バイナリツリー)のレベル数を表しているとします。この木の葉ノードには、1 から n までの番号が順に割り当てられています(n は葉ノードの総数)。また、各親ノードの値は、その 2 つの子ノードの値の合計となります。 今回の課題は、この完全二分木に含まれるすべてのノードの値の合計を出力するプログラムを作成することです。 例として、次のような木を考えてみましょう。 この木の場合、すべてのノードの合計は 30 になります。 解法のアプローチ この問題を注意深く観察すると、求めるべきは全ノードの値の総和です。葉ノードには 1 から

  2. Pythonで二分木の中から最大のBST(二分探索木)の合計値を見つけるプログラム

    問題の概要ある二分木が与えられたとします。この木の部分木の中に二分探索木(BST)が存在するかどうかを調べ、その中で最も大きなBSTを見つけ出し、そのノード値の合計を求めるのが目的です。合計値は、そのBSTに含まれる各ノードの値をすべて足し合わせたものになります。例えば、入力が次のような二分木だったとしましょう。この場合、出力は 12 となります。与えられた二分木の中に存在するBSTは次の部分木です。このBSTのノード値の合計 = 12 となります。解き方のアプローチこの問題を解くために、以下の手順で処理を進めます。変数 c := 0、m := null、value := 0 を初期化します。