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

C++で二分木を剪定する:1を含まない部分木を削除する再帰アルゴリズム

問題概要

二分木のルートノード root が与えられ、すべてのノードの値は 0 または 1 のいずれかであるとします。この木から、1 を含まないすべての部分木を削除した結果の木を求めるのが目的です。

たとえば、次のような木が与えられた場合 −

C++で二分木を剪定する:1を含まない部分木を削除する再帰アルゴリズム


解決のためのアプローチ

この問題は、再帰的な手法を用いて以下の手順で解決できます −

  • ノードを引数として受け取る再帰メソッド solve() を定義します。処理の流れは次のとおりです −
  • ノードが null の場合は、null を返します
  • ノードの左の子に対して solve(左の子) を実行し、その結果を左の子に代入します
  • ノードの右の子に対して solve(右の子) を実行し、その結果を右の子に代入します
  • 左の子が null であり、右の子も null であり、かつノードの値が 0 である場合は、null を返します
  • それ以外の場合は、そのノードを返します

この再帰処理では、木の末端(葉)から順に評価が行われるため、「1 を一切含まない部分木」がボトムアップ方式で効率よく削除されていきます。

実装例

より深く理解するために、以下の実装をご覧ください −

#include <bits/stdc++.h>
using namespace std;
class TreeNode{
   public:
   int val;
   TreeNode *left, *right;
   TreeNode(int data){
      val = data;
      left = NULL;
      right = NULL;
   }
};
void insert(TreeNode **root, int val){
   queue<TreeNode*> q;
   q.push(*root);
   while(q.size()){
      TreeNode *temp = q.front();
      q.pop();
      if(!temp->left){
         temp->left = new TreeNode(val);
         return;
      }else{
         q.push(temp->left);
      }
      if(!temp->right){
         temp->right = new TreeNode(val);
         return;
      }else{
         q.push(temp->right);
      }
   }
}
TreeNode *make_tree(vector<int> v){
   TreeNode *root = new TreeNode(v[0]);
   for(int i = 1; i<v.size(); i++){
      insert(&root, v[i]);
   }
   return root;
}
void tree_level_trav(TreeNode*root){
   if (root == NULL) return;
   cout << "[";
   queue<TreeNode *> q;
   TreeNode *curr;
   q.push(root);
   q.push(NULL);
   while (q.size() > 1) {
      curr = q.front();
      q.pop();
      if (curr == NULL){
         q.push(NULL);
      } else {
         if(curr->left)
            q.push(curr->left);
         if(curr->right)
            q.push(curr->right);
         if(curr == NULL){
            cout << "null" << ", ";
         }else{
            cout << curr->val << ", ";
         }  
      }
   }
   cout << "]"<<endl;
}
class Solution {
   public:
   TreeNode* pruneTree(TreeNode* node) {
      if(!node)return NULL;
      node->left = pruneTree(node->left);
      node->right = pruneTree(node->right);
      if(!node->left && !node->right && !node->val){
         return NULL;
      }
      return node;
   }
};
main(){
   vector<int> v = {1,1,0,1,1,0,1,0};
   TreeNode *root = make_tree(v);
   Solution ob;
   tree_level_trav(ob.pruneTree(root));
}

入力

[1,1,0,1,1,0,1,0]

出力

[1, 1, 0, 1, 1, 1]


  1. C++で最大二分木を構築する方法:再帰アルゴリズムと実装例を解説

    最大二分木(Maximum Binary Tree)とは? ここでは、すべての要素が一意(重複なし)である整数配列が与えられたとします。この配列から構築される「最大二分木」は、以下のように定義されます。 根(ルート)には、配列内の最大値が格納されます。 左部分木は、最大値を基準に分割された左側の部分配列から構築された最大二分木です。 右部分木は、最大値を基準に分割された右側の部分配列から構築された最大二分木です。 この定義に従って最大二分木を構築します。たとえば、入力が [3,2,1,6,0,5] の場合、構築される木は次の図のようになります。 解き方のアプローチ この問題は、再帰的な

  2. C++で二分木を二分探索木(BST)へ変換する方法を解説

    二分木(Binary Tree)とは二分木とは、木構造の各ノードが最大で2つの子ノードを持つことができる特別な木構造です。これらの子ノードは、それぞれ「左の子ノード」と「右の子ノード」と呼ばれます。シンプルな二分木の例は以下の通りです。二分探索木(BST)とは二分探索木(BST)は、以下のルールに従う特別な木構造です。左の子ノードの値は、常に親ノードの値より小さい右の子ノードの値は、常に親ノードの値より大きいすべてのノードが、それぞれ独立して二分探索木の性質を満たす二分探索木(BST)の例は以下の通りです。二分探索木は、検索や最小値・最大値の探索といった操作の計算量を削減するために用いられるデ