C++ でバイナリ検索ツリーデータ構造を実装する
このガイドでは、C++ でバイナリ検索ツリーデータ構造を実装する方法を示します。
C++ で struct
キーワードを使用してバイナリ検索ツリーを実装する
二分探索木(BST)は、二分木データ構造の特殊なケースです。データ構造は通常、バイナリ検索アルゴリズムを使用して高速検索するために、要素のソートされたリストを格納するために使用されます。通常のバイナリツリーとは対照的に、BST には、各ノードに key
と呼ばれる特別なデータメンバーがあり、一意の値を持っている必要があります。
BST のすべてのノードは、次の要件を満たす必要があります。key
値は、左側の子のサブツリー内のすべてのキーよりも大きく、右側の子のサブツリー内のすべてのキーよりも小さい必要があります。前のステートメントは、キー値が小さい要素がツリー階層の左側に配置されることを意味します。これにより、バイナリ検索を使用するのに最適な構造が得られます。
次のサンプルコードでは、BSTreeNode
という名前の struct
を定義します。これは、左右のノードへの 2つのポインタと、キーを示す string
メンバーで構成されます。キー値がノードに格納されているデータと同じである、最も単純なバージョンの BST を実装していることに注意してください。
一般に、プログラマーは、特定の問題の必要に応じて、他のデータメンバーを格納するための BST ノードを自由に定義できます。この定義は、特定の文字列(キー)を検索する必要がある、並べ替えられた文字列の配列をエミュレートするのに最適です。二分探索関数を実装する前に、BST オブジェクトを最初から作成する必要があります。したがって、文字列の事前定義されたベクトル
を使用して、新しい二分探索木を初期化します。
insertNode
関数は、ツリーのルートが引数として渡されたときに新しい子 BSTreeNode
を作成するための再帰的な実装です。ルートノード自体を作成する必要がある場合は、BSTreeNode
型へのポインタを宣言し、それに nullptr
を割り当て、そこに格納する必要のある対応する string
値とともに insertNode
に渡すことができます。リストを v1
の内容で初期化すると、printTree
関数を呼び出して、BST の inorder
トラバーサルと呼ばれるソートされた順序ですべてのキー値を出力できます。
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
struct BSTreeNode {
string key;
struct BSTreeNode *left{};
struct BSTreeNode *right{};
};
void insertNode(BSTreeNode *&root, const string &k) {
if (root == nullptr) {
root = new BSTreeNode;
root->key = k;
root->left = nullptr;
root->right = nullptr;
} else {
if (k < root->key)
insertNode(root->left, k);
else
insertNode(root->right, k);
}
}
void printTree(BSTreeNode *n) {
if (n != nullptr) {
printTree(n->left);
cout << n->key << "; ";
printTree(n->right);
}
}
int main() {
std::vector<string> v1{"camel", "wind", "zero", "maya", "aim", "born", "xen"};
BSTreeNode *root = nullptr;
for (const auto &item : v1) {
insertNode(root, item);
}
printTree(root);
return EXIT_SUCCESS;
}
出力:
aim; born; camel; maya; wind; xen; zero;
C++ で二分探索木の二分探索アルゴリズムを実装する
バイナリ検索アルゴリズムは、キーが階層に格納される順序付けのため、BST 構造で効率的です。BST には、挿入、削除、ルックアップの 3つの主要な操作が実装されています。
次の例では、ルックアップに重点を置いています。findNode
関数は、ルートノードを使用して関数に渡される BST 内の指定されたキーのルックアップを担当します。このコマンドは再帰的な性質のものであり、キーが格納されている BSTreeNode
へのポインタを返します。キー値がどのノードにも見つからない場合は、nullptr
が返されます。より良いデモンストレーションのために、ノードポインターを受け取り、キー値を cout
ストリームに出力して、findNode
関数の戻り値を関数に直接チェーンして出力する printNode
関数も実装しました。
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
struct BSTreeNode {
string key;
struct BSTreeNode *left{};
struct BSTreeNode *right{};
};
void insertNode(BSTreeNode *&root, const string &k) {
if (root == nullptr) {
root = new BSTreeNode;
root->key = k;
root->left = nullptr;
root->right = nullptr;
} else {
if (k < root->key)
insertNode(root->left, k);
else
insertNode(root->right, k);
}
}
BSTreeNode *findNode(BSTreeNode *root, const string &k) {
if (root == nullptr) return nullptr;
if (k == root->key) return root;
if (k < root->key)
return findNode(root->left, k);
else
return findNode(root->right, k);
}
void printNode(BSTreeNode *n) {
if (n != nullptr) {
cout << n->key << endl;
} else {
cout << "Not a valid node!" << endl;
}
}
int main() {
std::vector<string> v1{"camel", "wind", "zero", "maya", "aim", "born", "xen"};
BSTreeNode *root = nullptr;
for (const auto &item : v1) {
insertNode(root, item);
}
printNode(findNode(root, "zero"));
printNode(findNode(root, "zeroo"));
return EXIT_SUCCESS;
}
出力:
zero
Not a valid node!