データ構造の二分木 (例)

二分木とは何ですか?

バイナリーという言葉はXNUMXという意味です。 ツリーデータ構造「Binary Tree」において、各ノードが最大 XNUMX つの子ノード (左右のノード) を持つことができるツリーを意味します。 単純な二分木です。

ただし、最も頻繁に使用され、さまざまな使用例がある別のバイナリ ツリーがあります。これはバイナリ検索ツリー (BST) と呼ばれます。このツリーを使用すると、検索アルゴリズムを大幅に高速化でき、正確には log(n) の時間計算量になります。データ構造では、n はバイナリ ツリーのノードの数を意味します。

二分木と二分探索木の違いは何ですか?

BST と通常の二分木の違いは、BST の左側のノードがルート ノードよりも小さい値を持ち、右側のノードがルート ノードよりも大きい値を持つことです。 したがって、左側のサブツリーには常にルートより小さい値が含まれ、右側のサブツリーには常にルートより大きい値が含まれます。

二分木と二分探索木の違い

二分探索木の例

二分探索木の概念を説明するために次の例を見てみましょう。

二分探索木の例

ここでは、すべてのノードが指定された規律に従うことができます。 二分探索木の最大ノード数には公式があります。 上記のツリーを観察すると、すべてのリーフ ノードを除いて、各ノードに 4 つの子があることがわかります。 そして、指定された二分木の高さ(h)はXNUMXです。式は次のとおりです。 2h - 1。 したがって、15 になります。

二分探索木の例

二分探索木の例

上記の画像は完全なバイナリ ツリーまたはバランス バイナリ ツリーではなく、完全バイナリ ツリーまたはバランス バイナリ ツリーと呼ばれます。 AVL (別のタイプのバイナリ ツリー) と呼ばれる別のデータ構造があります。これは、バイナリ ツリーの高さを最適化し、図 3 のように BST の検索を高速化します。

上記のバイナリ ツリーの順序どおりのトラバーサルを計算してみてください。非減少のソートされた配列が生成され、トラバーサル アルゴリズムはバイナリ ツリーと同じになることがわかります。

二分木の種類

ここでは、バイナリ ツリーの重要なタイプをいくつか示します。

  • 完全なバイナリ ツリー: このバイナリ ツリーでは、各ノードが 0 または 2 つの子ノードを持つことができます。 このタイプのバイナリ ツリーでは、子ノードが 2 つだけ許可されません。 したがって、リーフ ノードを除くすべてのノードには XNUMX つの子が存在します。

二分木の種類

  • 完全なバイナリ ツリー: 各ノードには 0 個または 2 個のノードを含めることができます。 完全なバイナリ ツリーのように見えますが、すべてのリーフ要素は左側のサブツリーに偏っていますが、完全なバイナリ ツリーではノードが右側または左側のサブツリーに存在する可能性があります。

二分木の種類

  • 完璧な二分木: すべてのノードには 0 個または 2 個のノードが必要で、すべてのリーフ ノードは同じレベルまたは高さである必要があります。 完全なバイナリ ツリー構造の上記の例は、ノード 6 とノード 1,2,3、XNUMX、XNUMX が同じ高さではないため、完全なバイナリ ツリーではありません。 しかし、完全なバイナリ ツリーの例は、完全なバイナリ ツリーです。
  • 縮退したバイナリ ツリー: 各ノードには 1 つの子しか存在できません。検索、挿入、削除などのすべての操作には O(N) の時間がかかります。

二分木の種類

  • バランスの取れた二分木: この二分木では、左右のサブツリーの高さの差は最大でも 1 です。そのため、ノードを追加または削除するときに、ツリーの高さのバランスを再度調整する必要があります。 このタイプの自己バランス型二分木は、 AVLツリー.

二分木の種類

BST には 3 つの基本的な操作があります。これらについては以下で詳しく説明します。

C言語での二分木の実装と C++

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct Node
{
   int value;
   struct Node *left, *right;
}
struct Node *getEmptynode(int val)
{
   struct Node *tempNode = (struct Node *)malloc(sizeof(struct Node));
   tempNode->value = val;
   tempNode->left = NULL;
   tempNode->right = NULL;
   return tempNode;
}
struct Node *successor(struct Node *node)
{
    struct Node *present = node;
// going to the left most node
    while (present != NULL && present->left != NULL)
    {
       present = present->left;
    }
     return present;
 }
struct Node *insert(struct Node *node, int value)
{
   if (node == NULL)
   {
      return getEmptynode(value);
   }
   if (value < node->value)
   {
      node->left = insert(node->left, value);
   }
   else
   {
      node->right = insert(node->right, value);
   }
      return node;
}
int searchInBST(struct Node *node, int value)
{
   struct Node *current = node;
   while (current->value != value)
    {
    if (current->value > value)
      {
      current = current->left;
      }
    else
     {
     current = current->right;
     }
   if (current == NULL)
     {
    return 0;
     }
   }
return 1;
}
void inorder(struct Node *root)
{
 if (root != NULL)
  {
   inorder(root->left);
   cout << root->value << " ";
   inorder(root->right);
  }
}
struct Node *deleteNode(struct Node *node, int value)
{
 if (node == NULL)
  {
   return node;
  }
 if (value < node->value)
  {
   node->left = deleteNode(node->left, value);
  }
else if (value > node->value)
 {
   node->right = deleteNode(node->right, value);
 }
else
{
if (node->left == NULL)
 {
 struct Node *temp = node->right;
 free(node);
 return temp;
 }
 else if (node->right == NULL)
 {
 struct Node *temp = node->left;
 free(node);
 return temp;
  }
 struct Node *temp = successor(node->right);
 node->value = temp->value;
 node->right = deleteNode(node->right, temp->value);
}
return node;
}
int main()
 {
  struct Node *root = NULL;
  root = insert(root, 8);
  root = insert(root, 4);
  root = insert(root, 12);
  root = insert(root, 2);
  root = insert(root, 6);
  root = insert(root, 10);
  root = insert(root, 14);
  root = insert(root, 1);
  root = insert(root, 3);
  root = insert(root, 5);
  root = insert(root, 7);
  root = insert(root, 9);
  root = insert(root, 11);
  root = insert(root, 13);
  root = insert(root, 15);

 cout << "InOrder Traversal after inserting all nodes: " << endl;
 inorder(root);
 root = insert(root, -10);
 cout << "\nInOrder Traversal after inserting -10 : " << endl;
 inorder(root);
 cout << "\nSearching -5 in the BST: " << searchInBST(root, -5) << endl;
 cout << "Searching -10 in the BST: " << searchInBST(root, -10) << endl;
 root = deleteNode(root,8);
 cout<<"After deleting node 8, inorder traversal: "<<endl;
 inorder(root);
 root = deleteNode(root,-10);
 cout<<"\nAfter deleting node -10, inorder traversal: "<<endl;
 inorder(root);
}

出力:

InOrder Traversal after inserting all nodes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

InOrder Traversal after inserting -10 :
10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Searching -5 in the BST: 0
Searching -10 in the BST: 1

After deleting node 8, inorder traversal:
-10 1 2 3 4 5 6 7 9 10 11 12 13 14 15

After deleting node -10, inorder traversal:
1 2 3 4 5 6 7 9 10 11 12 13 14 15

バイナリツリーの実装 Python

class Node:
def __init__(self,value):
      self.left = None
      self.right = None
      self.value = value
def insert(root,value):
      if root == None:
          return Node(value)
      if value< root.value:
          root.left = insert(root.left,value)
      else:
          root.right = insert(root.right,value)
          return root
  def searchInBST(root,value):
      current = root
  while current.value != value:
  if current.value > value:
      current = current.left
  else:
      current = current.right
  if current == None:
      return "Not found"
      return "Found"
def inorder(root):
    if root != None:
      inorder(root.left)
      print(root.value,end=" ")
      inorder(root.right)
def successor(root):
    present = root
    while present != None and present.left != None:
    present = present.left
      return present
def deleteNode(root,value):
    if root == None:
      return root
    if value < root.value:
        root.left = deleteNode(root.left, value)
    elif value>root.value:
        root.right = deleteNode(root.right, value)
    else:
    if root.left == None:
        temp = root.right
        root = None
        return temp
    elif root.right == None:
        temp = root.left
        root = None
        return temp
        temp = successor(root.right)
        root.value = temp.value
        root.right = deleteNode(root.right, temp.value)
        return root
        root = Node(8)
        root = insert(root, 4)
        root = insert(root, 12)
        root = insert(root, 2)
        root = insert(root, 6)
        root = insert(root, 10)
        root = insert(root, 14)
        root = insert(root, 1)
        root = insert(root, 3)
        root = insert(root, 5)
        root = insert(root, 7)
        root = insert(root, 9)
        root = insert(root, 11)
        root = insert(root, 13)
        root = insert(root, 15)
  print("InOrder Traversal after inserting all nodes: ")
  inorder(root)
  root = insert(root, -10)
  print("\nInOrder Traversal after inserting -10 : ")
  inorder(root)
  print("\nSearching -5 in the BST: ",searchInBST(root, -5))
  print("Searching -5 in the BST: ",searchInBST(root, -10))
  root = deleteNode(root,8)
  print("After deleting node 8, inorder traversal:")
  inorder(root)
  root = deleteNode(root,-10)
  print("\nAfter deleting node -10, inorder traversal:")
  inorder(root)

出力:

InOrder Traversal after inserting all nodes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 

InOrder Traversal after inserting -10 : -10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 

Searching -5 in the BST: Not found 

Searching -5 in the BST: Found After deleting node 8, inorder traversal: -10 1 2 3 4 5 6 7 9 10 11 12 13 14 15 

After deleting node -10, inorder traversal: 1 2 3 4 5 6 7 9 10 11 12 13 14 15

二分木の応用

Binary Tree の一般的なアプリケーションをいくつか示します。

  • ノードデータをソート順に整理する
  • プログラミング言語ライブラリのマップおよびセット ノード オブジェクトで使用されます。
  • データ構造内の要素の検索

» 次のチュートリアルについて学ぶ 組み合わせアルゴリズム