C++ でバイナリ ツリー レベルごとにデータを出力する
- C++ でバイナリ ツリーのデータをレベルごとに出力するためのキューを使用したアルゴリズムの記述
- リンク リスト ノードを使用して、バイナリ ツリーのデータを C++ のレベルごとに出力する
- ハッシュ手法を使用して、C++ でレベルごとにバイナリ ツリーのデータを出力する
二分木のレベルごとのトラバーサルは、幅優先
トラバーサルとして知られています。 このチュートリアルでは、C++ でバイナリ ツリーのデータをレベルごとに出力する方法を説明し、このタスクを実行するためのさまざまな方法について説明します。
スタックは 深さ優先
トラバーサル用であるため、キューを使用することは、バイナリ ツリーのデータをレベルごとに出力する適切な方法です。 ただし、この目標を達成するには 3つの方法があります。キュー (またはリンク リスト ノード) を使用して独自のアルゴリズムを作成するか、ハッシング手法を使用します。
C++ でバイナリ ツリーのデータをレベルごとに出力するためのキューを使用したアルゴリズムの記述
C++ では、#include<queue>
を含めることでキューの機能を使用して、バイナリ ツリーのデータをレベルごとにソート順に出力するアルゴリズムを記述できます。 キューは FIFO (先入れ先出しの原則) に従うため、キューを初期化し、ルートをキューにプッシュする必要があります。
論理アルゴリズムを作成し、それを入力バイナリ ツリーに適用すると、null
ノードを使用できます (ノードを 改行
で区切るため)。 null
ノードとのやり取りは、未訪問のノードが現在のレベルに残っていないことを意味し、newline
を出力できることを思い出してください。
各バイナリ ツリー レベルの最後には、その終了を表す null
ノードが必要です。 タイプ ノードのデータを格納するキューを初期化し、root をそこにプッシュし、最後に null
ノードをキューにプッシュすると、null
ノードをレベルに挿入できます。
#include <iostream>
#include <queue>
using namespace std;
class binT_node {
public:
int nodeData;
// declare left and right nodes of the binary tree
binT_node* left;
binT_node* right;
binT_node(int data, binT_node* lef, binT_node* rig) {
nodeData = data;
left = lef;
right = rig;
}
};
void print_dataT(binT_node* root) {
queue<binT_node*> que;
que.push(root);
while (true) {
int orderLength = que.size();
if (orderLength == 0) {
break;
}
int i = 0;
while (i < orderLength) {
binT_node* nod = que.front();
cout << (nod->nodeData) << " ";
if (nod->left != NULL) {
que.push(nod->left);
}
if (nod->right != NULL) {
que.push(nod->right);
}
que.pop();
i++;
}
cout << endl;
}
}
int main() {
binT_node* rootNode;
rootNode = new binT_node(1, NULL, NULL);
rootNode->left = new binT_node(2, NULL, NULL);
rootNode->right = new binT_node(3, NULL, NULL);
rootNode->left->left = new binT_node(4, NULL, NULL);
rootNode->left->right = new binT_node(5, NULL, NULL);
rootNode->right->left = new binT_node(6, NULL, NULL);
rootNode->right->right = new binT_node(7, NULL, NULL);
print_dataT(rootNode);
return 0;
}
出力:
1
2 3
4 5 6 7
各反復で 1つのノードを出力する代わりに、1 回の反復で同じレベルのノードを出力することができます。これは、C++ で同様のアルゴリズムを作成する別のよく知られたアプローチです。
このアプローチは、キューを初期化し、それに root
ノードと null
ノードをプッシュすることを含め、最初のアプローチと少し似ています。
さらに、temp
が null
でない場合、ノード temp
の値を出力し、null でない場合は temp.left
をキューにプッシュし、null でない場合は temp.right
をキューにプッシュし、繰り返します。 キューが空になるまでの手順。
リンク リスト ノードを使用して、バイナリ ツリーのデータを C++ のレベルごとに出力する
ノードにアクセスしてその子ノードを FIFO キューに入れることは、キューをリンク リストとして実装することもできるため、標準的な方法です。 ただし、C++ の関数を使用して、バイナリ ツリーの現在のレベルを出力することは可能です。
最初に、リンク リスト ノードの ArrayList
を作成することにより、バイナリ ツリーのレベル順トラバーサルに queue(BFS)
を使用します。 変数はキューのサイズを格納でき、各バイナリ ツリー レベルですべてのノードを取得および操作するのに役立ちます。
ここで、キュー サイズを格納する変数が 0 より大きい間、変数にアクセスし、子をキューに追加してすべてのノードを取得、出力、または操作します。
この再帰的なソリューションは完全に機能しますが、キューやハッシング手法ほど効果的ではありません。
#include <iostream>
using namespace std;
class listNode {
public:
int data;
listNode *left, *right;
};
void print_data(listNode* root_node, int level_order);
int lev_height(listNode* node);
listNode* updatedNode(int data);
void printData_LevelOrder(listNode* root_node) {
int heig = lev_height(root_node);
int init;
for (init = 1; init <= heig; init++) print_data(root_node, init);
}
void print_data(listNode* root_node, int level_order) {
// in case of a `null` or empty root
if (root_node == NULL) return;
// in case if root represents `1`
if (level_order == 1) cout << root_node->data << " ";
// in case the root is greater than `1`
else if (level_order > 1) {
print_data(root_node->left, level_order - 1);
print_data(root_node->right, level_order - 1);
}
}
int lev_height(listNode* node_linkedlist) {
// in case of empty or `NULL`
if (node_linkedlist == NULL)
return 0;
else {
int level_leftHeight = lev_height(node_linkedlist->left);
int level_rightHeight = lev_height(node_linkedlist->right);
// in case the left node is greater than the right node
if (level_leftHeight > level_rightHeight) {
return (level_leftHeight + 1);
}
// in case the right node is greater than the left node
else {
return (level_rightHeight + 1);
}
}
}
listNode* updatedNode(int _listdata) {
listNode* list_node = new listNode();
list_node->data = _listdata;
list_node->left = NULL;
list_node->right = NULL;
return (list_node);
}
int main() {
listNode* linkedlistNode = updatedNode(1);
linkedlistNode->left = updatedNode(2);
linkedlistNode->right = updatedNode(3);
linkedlistNode->left->left = updatedNode(4);
linkedlistNode->left->right = updatedNode(5);
cout << "Level by Level Data Insertion to a Binary Tree is Complete! \n";
printData_LevelOrder(linkedlistNode);
return 0;
}
出力:
Level by Level Data Insertion to a Binary Tree is Complete!
1 2 3 4 5
printLevelOrder
と printCurrentLevel
は、このアプローチ (リンクされたリストを使用してバイナリ ツリーのデータを出力する) のサブ関数であり、それぞれ、特定のレベルですべてのノードを出力するか、バイナリ ツリーのレベル順トラバーサルを出力します。 .
さらに、printLevelOrder
サブ関数は、printCurrentLevel
関数を利用して、バイナリ ツリーのすべてのレベルのルートからノードを 1つずつ出力できます。
Breath-First Search
(BFS) の時間計算量は O(n^2)
です。ここで、n
はバイナリ ツリー ノードの最大数を表し、O(h)
は、 h
がバイナリ ツリーの完全な高さを表す C++ プログラム。
このチュートリアルで見つける各アルゴリズムは、以下を含むすべてのタイプのバイナリ ツリーを処理できます。 完全な、完全な、完全な、退化した、または病的な、歪んだ、バランスのとれた二分木。
ハッシュ手法を使用して、C++ でレベルごとにバイナリ ツリーのデータを出力する
ハッシュ テクニックの一部として、ハッシュ テーブルを使用すると、バイナリ ツリーのデータをレベルごとに出力できます。また、ハッシュ テーブルのルックアップ時間が平均で O(1)
かかる非常に有用なデータ構造であることが証明されています。
アルゴリズムとバイナリデータ構造に関連するいくつかの問題を非常に効率的に解決して、時間の複雑さを軽減できます。
ハッシングには multimap
が含まれています。これにより、1つのキーを複数の値にマッピングし、それを使用してバイナリ ツリー ノードとそのレベルを格納できます。
ハッシュ手法は、バイナリ ツリー レベル番号 (変数に格納されている) をキーとして使用し、親ノードまたはバイナリ ツリーの最初のレベルから開始して、各レベルに対応するすべてのノードを出力します。
#include <iostream>
// associative container that contains key-value pairs
// search, insert and remove elements in average constant-time complexity
#include <unordered_map>
#include <vector> // initialize the vector contents
using namespace std;
// data structure creation | fulfill the purpose of storing data in a binary
// table
struct _hashnode {
int key;
_hashnode *left, *right;
// `key` -> `_nodekey` will contain all the binary tree info to arrange the
// nodes
_hashnode(int _nodekey) {
this->key = _nodekey;
this->left = this->right = nullptr;
}
};
// enable nodes storage in a map (to traverse the tree in a pre_order fashion)
// corresponding to the node's level
void hash_preorder(_hashnode* hash_root, int level, auto& map) {
// initially: empty binary table
if (hash_root == nullptr) {
return;
}
// current node and its level insertion into the map
map[level].push_back(hash_root->key);
hash_preorder(hash_root->left, level + 1, map);
hash_preorder(hash_root->right, level + 1, map);
}
// recursive function | fulfill the purpose of printing binary tree's level
// order traversal
void traversal_throughHash(_hashnode* hash_root) {
// creation of a `null` or an empty map | to store nodes between the given
// levels of a binary tree
unordered_map<int, vector<int>> map;
/* level-wise insertion of nodes to the map after the tree traversal */
hash_preorder(hash_root, 1, map);
for (int init = 1; map[init].size() > 0; init++) {
cout << "[Binary Tree] Level " << init << ":- ";
for (int juan : map[init]) {
cout << juan << " ";
}
cout << endl;
}
}
int main() {
_hashnode* hash_Root = new _hashnode(15);
hash_Root->left = new _hashnode(10);
hash_Root->right = new _hashnode(20);
hash_Root->left->left = new _hashnode(8);
hash_Root->left->right = new _hashnode(12);
hash_Root->right->left = new _hashnode(16);
hash_Root->right->right = new _hashnode(25);
hash_Root->right->right->right = new _hashnode(30);
traversal_throughHash(hash_Root);
return 0;
}
出力:
[Binary Tree] Level 1:- 15
[Binary Tree] Level 2:- 10 20
[Binary Tree] Level 3:- 8 12 16 25
[Binary Tree] Level 4:- 30
一般に、バイナリ ツリーは、最上位ノードが parent
または root
ノードであり、各 parent
ノードが子ノードのペアを表すデータ構造として機能します。
二分木探索には 4つの一般的な方法があり、レベルごとの順序探索は最も効率的な方法の 1つです。
比較による並べ替え
に基づくアルゴリズムで、n log n
のパフォーマンスより優れているものはないというのは事実です。 バイナリ ティーの各ノードは、その子ノード (ai ≤ aj
) 間の比較を表し、それらは n!
の 1つを表します。
二分木には、n = (2^h) - 1
ノードが含まれます。ここで、h
は二分木の高さを表し、葉以外のすべてのノードには、右と左の両方の子ノードがあります。
n!
を持つツリーに対して h = [log(n!)]
を計算することにより、バイナリ ツリーの高さを決定できます。 葉ノードと h = log(n + 1)
高さ。
Hassan is a Software Engineer with a well-developed set of programming skills. He uses his knowledge and writing capabilities to produce interesting-to-read technical articles.
GitHub