木の基本概念
ツリーは、階層関係に従って相互に接続されたノードで構成される階層データ構造です。ツリーには次の基本概念があります。
-
ルート ノード: 親ノードを持たないツリーの最上位ノード。
-
子ノード: ツリー内の各ノードは、0 個以上の子ノードを持つことができます。
-
リーフノード: 子ノードを持たないノードをリーフノードと呼びます。
-
親ノード: ルート ノードを除くすべてのノードは親ノードを持つことができます。
-
深さ: ノードが配置されているレベルを深さといいます。ルート ノードの深さは 0、その子ノードの深さは 1 などとなります。
二分木と二分探索木 (BST) の定義
バイナリ ツリーは、各ノードが最大 2 つの子 (左の子と右の子) を持つ特別な種類のツリーです。
**二分探索ツリー (BST)** は、各ノードが次のルールに従う二分木です。
-
左側のサブツリー内のすべてのノードの値は、現在のノードの値より小さくなります。
-
右側のサブツリー内のすべてのノードの値が、現在のノードの値より大きくなります。
この順序性により、二分探索ツリーは検索および並べ替え操作に適しています。
ツリートラバース法
ツリーを走査するとは、ツリー内のノードを特定の順序で訪問することを意味します。ツリートラバーサルの一般的な方法は次の 3 つです。
-
事前順序トラバーサル: 最初にルート ノードにアクセスし、次に左のサブツリーと右のサブツリーを順番にトラバースします。
-
順序トラバーサル: 最初に左側のサブツリーをトラバースし、次にルート ノードにアクセスし、最後に右側のサブツリーをトラバースします。インオーダートラバーサルを使用して BST をソートできます。
-
事後走査: 最初に左側のサブツリーを走査し、次に右側のサブツリーを走査し、最後にルート ノードにアクセスします。
以下は、バイナリ ツリーを作成し、順序走査を実行する簡単な C++ の例です。
#include <iostream>
// 二叉树节点定义
struct TreeNode {
int data; // 节点数据
TreeNode* left; // 左子节点
TreeNode* right; // 右子节点
};
// 中序遍历函数
void inOrderTraversal(TreeNode* root) {
if (root != nullptr) {
inOrderTraversal(root->left);
std::cout << root->data << " ";
inOrderTraversal(root->right);
}
}
int main() {
// 创建二叉树
TreeNode* root = new TreeNode{
1, nullptr, nullptr};
root->left = new TreeNode{
2, nullptr, nullptr};
root->right = new TreeNode{
3, nullptr, nullptr};
// 中序遍历
inOrderTraversal(root);
return 0;
}
操作結果:
練習問題:
-
二分木と二分探索木の違いは何ですか? 二分探索ツリーの使用を選択するのはどのような場合ですか?
-
インオーダートラバーサルの概念を説明します。二分探索ツリーで順序トラバーサルが役立つのはなぜですか?
-
データの保存と編成には、配列やリンク リストなどの線形データ構造よりもツリー構造の方が適している状況を説明します。
-
単純なバイナリ ツリーを作成し、順序トラバーサルを実行してノードの値を出力する C++ プログラムを作成してください。
二分木と二分探索木の違いは何ですか? 二分探索ツリーの使用を選択するのはどのような場合ですか?
-
違い: 主な違いは秩序です。バイナリ ツリーは、各ノードが最大 2 つの子ノードを持つツリー構造です。二分探索木 (BST) は、順序付けされた特別な二分木です。BST では、左側のサブツリーのすべてのノードの値は現在のノードの値より小さく、右側のサブツリーのすべてのノードの値は現在のノードの値より大きくなります。
-
BST を選択する場合: BST の使用を選択するケースとしては、効率的な検索および並べ替え操作が必要な場合が挙げられます。BST の順序付けされた性質により、検索操作が非常に高速になり、平均時間計算量は O(log n) (n はツリー内のノードの数) になります。さらに、BST は、高速な検索と挿入を必要とする辞書やデータベース インデックスなどのアプリケーションの実装にも使用できます。
インオーダートラバーサルの概念を説明します。二分探索ツリーで順序トラバーサルが役立つのはなぜですか?
-
インオーダートラバーサルはツリートラバーサル手法の1つであり、その基本的な概念は、ツリー内のノードを左サブツリー、ルートノード、右サブツリーの順序でトラバースすることです。順序トラバーサルでは、最初に左側のサブツリー内のすべてのノードがトラバースされ、次にルート ノードにアクセスし、最後に右側のサブツリー内のすべてのノードがトラバースされます。
-
BST における順序トラバーサルの重要性: BST では、順序トラバーサルによりツリー内のノードに昇順でアクセスできます。これは、順序付けられたノードのシーケンスが、順序トラバーサルを通じて取得できることを意味します。したがって、BST ではインオーダー トラバーサルが非常に便利です。インオーダー トラバーサルは、ツリー上で並べ替え操作を実装するために使用でき、順序付けられたシーケンス内でターゲット値を迅速に見つけることができるため、検索操作にも使用できます。
データの保存と編成には、配列やリンク リストなどの線形データ構造よりもツリー構造の方が適している状況を説明します。
- シナリオ例: ファイルシステムの整理。ファイル システムは通常、ツリー構造を使用してファイルとフォルダーを整理します。各フォルダーにはファイルやその他のフォルダーを含めることができ、ルート ノードが最上位のディレクトリを表し、リーフ ノードがファイルを表すツリー構造を形成します。このツリー構造により、ファイル システムはファイルの整理、検索、アクセスが容易になります。
注: この場合、ツリー構造の方がファイル間の階層関係や編成構造を明確に表現できるため、より適していますが、通常、線形データ構造 (配列など) ではこの複雑さを表現するには不十分です。
単純なバイナリ ツリーを作成し、順序トラバーサルを実行してノードの値を出力する C++ プログラムを作成してください。
バイナリ ツリーを作成し、順序トラバーサルを実行します。
#include <iostream>
// 二叉树节点定义
struct TreeNode {
int data; // 节点数据
TreeNode* left; // 左子节点
TreeNode* right; // 右子节点
};
// 中序遍历函数
void inOrderTraversal(TreeNode* root) {
if (root != nullptr) {
inOrderTraversal(root->left);
std::cout << root->data << " ";
inOrderTraversal(root->right);
}
}
int main() {
// 创建二叉树
TreeNode* root = new TreeNode{
4, nullptr, nullptr};
root->left = new TreeNode{
2, nullptr, nullptr};
root->right = new TreeNode{
6, nullptr, nullptr};
root->left->left = new TreeNode{
1, nullptr, nullptr};
root->left->right = new TreeNode{
3, nullptr, nullptr};
root->right->left = new TreeNode{
5, nullptr, nullptr};
root->right->right = new TreeNode{
7, nullptr, nullptr};
// 中序遍历
inOrderTraversal(root);
return 0;
}
操作結果:
このプログラムは単純なバイナリ ツリーを作成し、順序トラバーサルを使用してノード値を出力します。