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

C++で二分木における最も深い奇数レベルの葉ノードの深さを求める方法

二分木の中で「奇数レベル」に存在する葉ノードのうち、最も深い位置にあるものの深さを求めるアルゴリズムを、C++のコード例とともに解説します。

ツリーノード構造体の定義

まず、int型のキーと左右の子ノードへのポインタを持つ、ツリーノードを表す構造体を定義します。最初に作成されたノードはルートノードとなり、それ以降に作成されるノードは子ノードとして扱われます。

struct Node {
int data;
struct Node *leftChild, *rightChild;
};

createNode関数の実装

次に、createNode(int key)関数を作成します。この関数はint型のキー値を受け取り、ノードのdataメンバーに代入します。戻り値としては、生成されたNode構造体へのポインタを返します。また、新しく作成されたノードの左子・右子はどちらもNULLに初期化されます。

Node* createNode(int data){
Node* node = new Node;
node->data = data;
node->leftChild = node->rightChild = NULL;
return node;
}

isLeaf関数の実装

続いて、isLeaf(Node *currentNode)関数を定義します。この関数は引数として受け取ったノードが子を持たないかどうかを判定し、葉ノードであればtrue、そうでなければfalseを返します。

bool isLeaf(Node *currentNode){
return (currentNode->leftChild == NULL &&
currentNode->rightChild == NULL);
}

deepestOddLvlDepth関数の実装

deepestOddLvlDepth(Node *currentNode, int currentLevel=0)関数は、現在のノードと現在のレベルを引数として受け取ります。currentLevelにはデフォルト引数として0が設定されているため、呼び出し時に値を渡さなくても動作します。currentNodeがNULLの場合は0を返します。

再帰呼び出しが行われるたびにcurrentLevelは1ずつ増加し、ベース条件が満たされるまで処理が繰り返されます。その後、現在のノードが「奇数レベルの葉ノード」であるかどうかを判定します。左右の子を順に辿ることで最も深い奇数レベルの葉ノードの深さを求め、leftChildLevelとrightChildLevelの最大値をmain関数へ返して結果を出力します。

int deepestOddLvlDepth(Node *currentNode, int currentLevel=0){
if ( currentNode == NULL)
return 0;
currentLevel ++;
if ( currentLevel % 2 != 0 && isLeaf(currentNode))
return currentLevel;
int leftChildLevel = deepestOddLvlDepth(currentNode->leftChild,currentLevel);
int rightChildLevel = deepestOddLvlDepth(currentNode->rightChild,currentLevel);
return max(leftChildLevel,rightChildLevel);
}

なお、このアルゴリズムは木のすべてのノードを一度ずつ訪問するため、計算量はノード数をNとするとO(N)になります。

サンプルコード全体

以下に、二分木における最も深い奇数レベルの葉ノードの深さを求める完全な実装例を示します。

#include<iostream>
using namespace std;
struct Node{
int key;
struct Node *leftChild, *rightChild;
};
Node* createNode(int key){
Node* node = new Node;
node->key = key;
node->leftChild = node->rightChild = NULL;
return node;
}
bool isLeaf(Node *currentNode){
return (currentNode->leftChild == NULL &&
currentNode->rightChild == NULL);
}
int deepestOddLvlDepth(Node *currentNode, int currentLevel=0){
if ( currentNode == NULL)
return 0;
currentLevel ++;
if ( currentLevel % 2 != 0 && isLeaf(currentNode))
return currentLevel;
int leftChildLevel = deepestOddLvlDepth(currentNode->leftChild,currentLevel);
int rightChildLevel = deepestOddLvlDepth(currentNode->rightChild,currentLevel);
return max(leftChildLevel,rightChildLevel);
}
int main(){
Node *root = createNode(15);
root->leftChild = createNode(33);
root->rightChild = createNode(18);
root->rightChild->leftChild = createNode(19);
root->rightChild->rightChild = createNode(20);
root->rightChild->rightChild->leftChild = createNode(28);
root->rightChild->rightChild->rightChild = createNode(29);
cout << "The depth of the deepest odd level leaf node is: "<<deepestOddLvlDepth(root) << endl;
return 0;
}

実行結果

このサンプルでは、ルート(15)をレベル1とし、33と18がレベル2、19と20がレベル3、28と29がレベル4に配置されています。葉ノードの中で奇数レベルに属するのは19(レベル3)のみのため、結果は3となります。上記のコードを実行すると、次の出力が得られます。

The depth of the deepest odd level leaf node is: 3
  1. C++の二分探索木(BST)で最小値のノードを見つける方法

    二分探索木(Binary Search Tree、BST)が与えられたとき、その木の中から最小の要素を見つけることを考えます。例えば、以下のようなBSTがあるとします。この場合、最小要素は 1 になります。考え方二分探索木の重要な性質として、左部分木には必ず親ノードより小さい値が格納されるというものがあります。この性質を利用すると、次の手順で最小要素を見つけることができます。ルートノードから探索を開始します。現在のノードの左の子が NULL でない間、左の子へ移動を繰り返します。左の子が NULL になったノードの値が、木全体の中で最小の要素です。この操作の計算量は木の高さに依存し、平衡な二分

  2. C++で二分木の奇数レベルにあるノードを出力するプログラム

    このチュートリアルでは、与えられた二分木(バイナリツリー)の中から、奇数レベルに存在するノードを出力するC++プログラムについて解説します。 本プログラムでは、ルートノードのレベルを「1」と定義し、それ以降のレベルは交互にカウントしていきます。つまり、レベル1・3・5…といった奇数番目の階層に属するノードが出力の対象となります。 例として、以下のような二分木が与えられた場合を考えてみましょう。 この二分木の場合、奇数レベルに存在するノードは 1, 4, 5, 6 となります。 アルゴリズムの考え方 実装には再帰呼び出しを利用します。ルートから探索を開始し、現在のレベルが奇数かどうかをブール