logo

Вступ до бінарного дерева – Навчальні посібники зі структури даних і алгоритмів

Бінарне дерево це нелінійна структура даних де кожен вузол має не більше двох дітей. У цій статті ми розглянемо всі основи бінарного дерева, операції з бінарним деревом, його реалізацію, переваги та недоліки, що допоможе вам вирішити всі проблеми на основі бінарного дерева.

Зміст

Що таке бінарне дерево?

Двійкове дерево - це a структура даних дерева (нелінійна) в якому кожен вузол може мати не більше двох дітей які називаються ліва дитина і права дитина .



Найвищий вузол у бінарному дереві називається корінь , а самі нижні вузли називаються листя . Бінарне дерево можна візуалізувати як ієрархічну структуру з коренем у верхній частині та листям унизу.

Представлення двійкового дерева

Кожен вузол у бінарному дереві складається з трьох частин:

  • Дані
  • Покажчик на ліву дитину
  • Вказівник на праву дитину

змінна bash

Нижче наведено представлення вузла бінарного дерева різними мовами:

C++
// Use any below method to implement Nodes of tree // Method 1: Using 'struct' to make // user-define data type struct node {  int data;  struct node* left;  struct node* right; }; // Method 2: Using 'class' to make // user-define data type class Node { public:  int data;  Node* left;  Node* right; };>
C
// Structure of each node of the tree struct node {  int data;  struct node* left;  struct node* right; };>
Java
// Class containing left and right child // of current node and key value class Node {  int key;  Node left, right;  public Node(int item)  {  key = item;  left = right = null;  } }>
Python
# A Python class that represents # an individual node in a Binary Tree class Node: def __init__(self, key): self.left = None self.right = None self.val = key>
C#
// Class containing left and right child // of current node and key value class Node {  int key;  Node left, right;  public Node(int item)  {  key = item;  left = right = null;  } }>
JavaScript
>

Типи бінарного дерева

Двійкове дерево можна класифікувати на кілька типів на основі кількох факторів:

Операції над бінарним деревом

1. Вставка в бінарне дерево

Ми можемо вставити вузол у будь-яке місце у бінарному дереві, вставивши вузол як лівий або правий дочірній елемент будь-якого вузла або зробивши вузол коренем дерева.

Алгоритм вставки вузла в бінарне дерево:

  • Перевірте, чи є вузол у бінарному дереві, у якому відсутній лівий дочірній елемент. Якщо такий вузол існує, вставте новий вузол як його лівий дочірній елемент.
  • Перевірте, чи є вузол у бінарному дереві, у якому відсутній правий дочірній елемент. Якщо такий вузол існує, вставте новий вузол як його правий дочірній елемент.
  • Якщо ми не знайдемо жодного вузла з відсутнім лівим чи правим дочірнім елементом, тоді знайдіть вузол, у якому відсутні обидва дочірні елементи, і вставте цей вузол як його лівий чи правий дочірній елемент.

2. Обхід бінарного дерева

Обхід бінарного дерева передбачає відвідування всіх вузлів бінарного дерева. Алгоритми обходу дерева можна розділити на дві категорії:

  • Алгоритми пошуку в глибину (DFS).
  • Алгоритми пошуку в ширину (BFS).

Алгоритми пошуку в глибину (DFS):

  • Обхід попереднього замовлення (поточний-ліво-право): Відвідайте поточний вузол перед відвідуванням будь-яких вузлів усередині лівого чи правого піддерева. Тут обхід корінь – лівий дочірній – правий дочірній. Це означає, що спочатку проходить кореневий вузол, потім його лівий дочірній вузол і, нарешті, правий дочірній вузол.
  • Обхід порядку (зліва-потоку-право): Відвідайте поточний вузол після відвідування всіх вузлів усередині лівого піддерева, але перед відвідуванням будь-якого вузла в межах правого піддерева. Тут обхід лівий дочірній – корінь – правий дочірній. Це означає, що спочатку проходить лівий дочірній елемент, потім його кореневий вузол і, нарешті, правий дочірній вузол.
  • Обхід після замовлення (зліва-право-потоку): Перейти до поточного вузла після відвідування всіх вузлів лівого та правого піддерева. Тут обхід лівий дочірній – правий дочірній – корінь. Це означає, що лівий дочірній елемент пройшов спочатку правий дочірній елемент і, нарешті, його кореневий вузол.

Алгоритми пошуку в ширину (BFS):

  • Обхід порядку рівня: Відвідайте вузли рівень за рівнем і зліва направо на одному рівні. Тут обхід відбувається по рівнях. Це означає, що першим пройшов крайній лівий нащадок, а потім пройшли інші нащадки того самого рівня зліва направо.

3. Видалення в бінарному дереві

Ми можемо видалити будь-який вузол у бінарному дереві та змінити порядок вузлів після видалення, щоб знову сформувати дійсне двійкове дерево.

ініціалізація списку python

Алгоритм видалення вузла в бінарному дереві:

  • Починаючи з кореня, знайдіть найглибший і правий вузол у бінарному дереві та вузол, який ми хочемо видалити.
  • Замініть дані найглибшого правого вузла вузлом, який потрібно видалити.
  • Потім видаліть найглибший правий вузол.

4. Пошук у бінарному дереві

Ми можемо шукати елемент у вузлі, використовуючи будь-яку техніку обходу.

Алгоритм пошуку вузла у бінарному дереві:

  • Почніть з кореневого вузла.
  • Перевірте, чи поточне значення вузла дорівнює цільовому значенню.
  • Якщо значення поточного вузла дорівнює цільовому значенню, то цей вузол є необхідним вузлом.
  • В іншому випадку, якщо значення вузла не дорівнює цільовому значенню, почніть пошук у лівому та правому дочірніх елементах.
  • Якщо ми не знайдемо жодного вузла, значення якого дорівнює цільовому, це значення не присутнє в дереві.

Допоміжні операції над бінарним деревом

Реалізація бінарного дерева

Нижче наведено код для вставки, видалення та обходу бінарного дерева:

C
#include  // Node structure to define the structure of the node typedef struct Node {  int data;  struct Node *left, *right; } Node; // Function to create a new node Node* newNode(int val) {  Node* temp = (Node*)malloc(sizeof(Node));  temp->дані = значення;  temp->left = temp->right = NULL;  зворотна температура; } // Функція для вставки вузлів Node* insert(Node* root, int data) { // Якщо дерево порожнє, новий вузол стає коренем if (root == NULL) { root = newNode(data);  повернути корінь;  } // Черга для обходу дерева та пошуку позиції для вставки вузла Node* queue[100];  int front = 0, rear = 0;  queue[rear++] = корінь;  while (front != rear) { Node* temp = queue[front++];  // Вставити вузол як лівий дочірній елемент батьківського вузла if (temp->left == NULL) { temp->left = newNode(data);  перерва;  } // Якщо лівий дочірній елемент не є нульовим, надішліть його до черги else queue[rear++] = temp->left;  // Вставити вузол як правий дочірній елемент батьківського вузла if (temp->right == NULL) { temp->right = newNode(data);  перерва;  } // Якщо правий дочірній елемент не нульовий, надішліть його до черги else queue[rear++] = temp->right;  } повернути корінь; } /* Функція видалення заданого найглибшого вузла (d_node) у бінарному дереві */ void deletDeepest(Node* root, Node* d_node) { Node* queue[100];  int front = 0, rear = 0;  queue[rear++] = корінь;  // Виконати обхід порядку рівня до останнього вузла Node* temp;  while (front != rear) { temp = queue[front++];  if (temp == d_node) { temp = NULL;  вільний (d_node);  повернення;  } if (temp->right) { if (temp->right == d_node) { temp->right = NULL;  вільний (d_node);  повернення;  } else queue[rear++] = temp->right;  } if (temp->left) { if (temp->left == d_node) { temp->left = NULL;  вільний (d_node);  повернення;  } else queue[rear++] = temp->left;  } } } /* Функція видалення елемента у бінарному дереві */ Node* deletion(Node* root, int key) { if (!root) return NULL;  if (root->left == NULL && root->right == NULL) { if (root->data == key) return NULL;  інакше повернути корінь;  } Node* queue[100];  int front = 0, rear = 0;  queue[rear++] = корінь;  Node* temp;  Node* key_node = NULL;  // Виконайте обхід порядку рівня, щоб знайти найглибший вузол (temp) і вузол, який потрібно видалити (key_node) while (front != rear) { temp = queue[front++];  if (temp->data == ключ) key_node = temp;  if (temp->left) queue[rear++] = temp->left;  if (temp->right) queue[rear++] = temp->right;  } if (key_node != NULL) { int x = temp->data;  key_node->data = x;  deletDeepest(root, temp);  } повернути корінь; } // Обхід дерева за порядком (ліворуч – корінь – праворуч) void inorderTraversal(Node* root) { if (!root) return;  inorderTraversal(корінь->ліворуч);  printf('%d ', корінь->дані);  inorderTraversal(root->right); } // Попередній обхід дерева (корінь - ліворуч - праворуч) void preorderTraversal(Node* root) { if (!root) return;  printf('%d ', корінь->дані);  preorderTraversal(root->left);  preorderTraversal(root->right); } // Обхід дерева Postorder (Ліворуч - Праворуч - Корінь) void postorderTraversal(Node* root) { if (root == NULL) return;  postorderTraversal(корінь->ліворуч);  postorderTraversal(корінь->справа);  printf('%d ', корінь->дані); } // Функція для обходу дерева порядку рівня void levelorderTraversal(Node* root) { if (root == NULL) return;  // Черга для проходження порядку рівня Node* queue[100];  int front = 0, rear = 0;  queue[rear++] = корінь;  while (front != rear) { Node* temp = queue[front++];  printf('%d ', temp->data);  // Проштовхнути лівого дочірнього елемента в чергу if (temp->left) queue[rear++] = temp->left;  // Проштовхнути правий дочірній елемент у чергу if (temp->right) queue[rear++] = temp->right;  } } /* Функція драйвера для перевірки наведеного вище алгоритму. */ int main() { Node* root = NULL;  // Вставка вузлів root = insert(root, 10);  корінь = вставити (корінь, 20);  корінь = вставити (корінь, 30);  корінь = вставка (корінь, 40);  printf('Обхід попереднього порядку: ');  preorderTraversal(корінь);  printf('
Обхід у порядку: ');  inorderTraversal(корінь);  printf('
Обхід після замовлення: ');  postorderTraversal(корінь);  printf('
Обхід порядку рівня: ');  levelorderTraversal(корінь);  // Видалення вузла з даними = 20 root = deletion(root, 20);  printf('
Обхід у порядку після видалення: ');  inorderTraversal(корінь);  повернути 0; }>
Java
import java.util.LinkedList; import java.util.Queue; // Node class to define the structure of the node class Node {  int data;  Node left, right;  // Parameterized Constructor  Node(int val) {  data = val;  left = right = null;  } } public class BinaryTree {  // Function to insert nodes  public static Node insert(Node root, int data) {  // If tree is empty, new node becomes the root  if (root == null) {  root = new Node(data);  return root;  }  // Queue to traverse the tree and find the position to  // insert the node  Queueq = новий LinkedList();  q.offer(корінь);  while (!q.isEmpty()) { Node temp = q.poll();  // Вставити вузол як лівий дочірній елемент батьківського вузла if (temp.left == null) { temp.left = new Node(data);  перерва;  } // Якщо лівий дочірній елемент не має значення null, надішліть його // до черги else q.offer(temp.left);  // Вставити вузол як правий дочірній елемент батьківського вузла if (temp.right == null) { temp.right = new Node(data);  перерва;  } // Якщо правий дочірній елемент не є null, надішліть його // до черги else q.offer(temp.right);  } повернути корінь;  } /* функція видалення заданого найглибшого вузла (d_node) у бінарному дереві */ public static void deletDeepest(Node root, Node d_node) { Queueq = новий LinkedList();  q.offer(корінь);  // Виконати обхід порядку рівня до останнього вузла Node temp;  while (!q.isEmpty()) { temp = q.poll();  if (temp == d_node) { temp = null;  d_node = нуль;  повернення;  } if (temp.right != null) { if (temp.right == d_node) { temp.right = null;  d_node = нуль;  повернення;  } else q.offer(temp.right);  } if (temp.left != null) { if (temp.left == d_node) { temp.left = null;  d_node = нуль;  повернення;  } else q.offer(temp.left);  } } } /* функція видалення елемента у бінарному дереві */ public static Node deletion(Node root, int key) { if (root == null) return null;  if (root.left == null && root.right == null) { if (root.data == ключ) повертає null;  інакше повернути корінь;  }  Чергаq = новий LinkedList();  q.offer(корінь);  Node temp = новий вузол (0);  Вузол key_node = null;  // Виконайте обхід порядку рівня, щоб знайти // найглибший вузол (temp) і вузол, який потрібно видалити (key_node) while (!q.isEmpty()) { temp = q.poll();  if (temp.data == ключ) key_node = temp;  if (temp.left != null) q.offer(temp.left);  if (temp.right != null) q.offer(temp.right);  } if (key_node != null) { int x = temp.data;  key_node.data = x;  deletDeepest(root, temp);  } повернути корінь;  } // Обхід дерева за порядком (Ліворуч - Корінь - Праворуч) public static void inorderTraversal(Node root) { if (root == null) return;  inorderTraversal(root.left);  System.out.print(root.data + ' ');  inorderTraversal(root.right);  } // Попередній обхід дерева (корінь - ліворуч - праворуч) public static void preorderTraversal(Node root) { if (root == null) return;  System.out.print(root.data + ' ');  preorderTraversal(root.left);  preorderTraversal(root.right);  } // Обхід дерева постпорядку (Ліворуч - Праворуч - Корінь) public static void postorderTraversal(Node root) { if (root == null) return;  postorderTraversal(root.left);  postorderTraversal(root.right);  System.out.print(root.data + ' ');  } // Функція для обходу дерева порядку рівня public static void levelorderTraversal(Node root) { if (root == null) return;  // Черга для проходження порядку рівня Чергаq = новий LinkedList();  q.offer(корінь);  while (!q.isEmpty()) { Node temp = q.poll();  System.out.print(temp.data + ' ');  // Проштовхнути лівого дочірнього елемента в чергу if (temp.left != null) q.offer(temp.left);  // Проштовхнути правий дочірній елемент у чергу if (temp.right != null) q.offer(temp.right);  } } /* Функція драйвера для перевірки наведеного вище алгоритму. */ public static void main(String[] args) { Node root = null;  // Вставка вузлів root = insert(root, 10);  корінь = вставити (корінь, 20);  корінь = вставити (корінь, 30);  корінь = вставка (корінь, 40);  System.out.print('Обхід попереднього замовлення: ');  preorderTraversal(корінь);  System.out.print('
Обхід у порядку: ');  inorderTraversal(корінь);  System.out.print('
Обхід після замовлення: ');  postorderTraversal(корінь);  System.out.print('
Обхід порядку рівня: ');  levelorderTraversal(корінь);  // Видалення вузла з даними = 20 root = deletion(root, 20);  System.out.print('
Обхід у порядку після видалення: ');  inorderTraversal(корінь);  } }>
Python
from collections import deque # Node class to define the structure of the node class Node: def __init__(self, val): self.data = val self.left = self.right = None # Function to insert nodes def insert(root, data): # If tree is empty, new node becomes the root if root is None: root = Node(data) return root # Queue to traverse the tree and find the position to insert the node q = deque() q.append(root) while q: temp = q.popleft() # Insert node as the left child of the parent node if temp.left is None: temp.left = Node(data) break # If the left child is not null push it to the queue else: q.append(temp.left) # Insert node as the right child of parent node if temp.right is None: temp.right = Node(data) break # If the right child is not null push it to the queue else: q.append(temp.right) return root # Function to delete the given deepest node (d_node) in binary tree def deletDeepest(root, d_node): q = deque() q.append(root) # Do level order traversal until last node while q: temp = q.popleft() if temp == d_node: temp = None del d_node return if temp.right: if temp.right == d_node: temp.right = None del d_node return else: q.append(temp.right) if temp.left: if temp.left == d_node: temp.left = None del d_node return else: q.append(temp.left) # Function to delete element in binary tree def deletion(root, key): if not root: return None if root.left is None and root.right is None: if root.data == key: return None else: return root q = deque() q.append(root) temp = None key_node = None # Do level order traversal to find deepest node (temp) and node to be deleted (key_node) while q: temp = q.popleft() if temp.data == key: key_node = temp if temp.left: q.append(temp.left) if temp.right: q.append(temp.right) if key_node is not None: x = temp.data key_node.data = x deletDeepest(root, temp) return root # Inorder tree traversal (Left - Root - Right) def inorderTraversal(root): if not root: return inorderTraversal(root.left) print(root.data, end=' ') inorderTraversal(root.right) # Preorder tree traversal (Root - Left - Right) def preorderTraversal(root): if not root: return print(root.data, end=' ') preorderTraversal(root.left) preorderTraversal(root.right) # Postorder tree traversal (Left - Right - Root) def postorderTraversal(root): if root is None: return postorderTraversal(root.left) postorderTraversal(root.right) print(root.data, end=' ') # Function for Level order tree traversal def levelorderTraversal(root): if root is None: return # Queue for level order traversal q = deque() q.append(root) while q: temp = q.popleft() print(temp.data, end=' ') # Push left child in the queue if temp.left: q.append(temp.left) # Push right child in the queue if temp.right: q.append(temp.right) # Driver function to check the above algorithm if __name__ == '__main__': root = None # Insertion of nodes root = insert(root, 10) root = insert(root, 20) root = insert(root, 30) root = insert(root, 40) print('Preorder traversal:', end=' ') preorderTraversal(root) print('
Inorder traversal:', end=' ') inorderTraversal(root) print('
Postorder traversal:', end=' ') postorderTraversal(root) print('
Level order traversal:', end=' ') levelorderTraversal(root) # Delete the node with data = 20 root = deletion(root, 20) print('
Inorder traversal after deletion:', end=' ') inorderTraversal(root)>
C#
using System; using System.Collections.Generic; // Node class to define the structure of the node public class Node {  public int data;  public Node left, right;  // Parameterized Constructor  public Node(int val)  {  data = val;  left = right = null;  } } public class Program {  // Function to insert nodes  public static Node Insert(Node root, int data)  {  // If tree is empty, new node becomes the root  if (root == null)  {  root = new Node(data);  return root;  }  // Queue to traverse the tree and find the position to insert the node  Queueq = нова черга();  q.Enqueue(корінь);  while (q.Count != 0) { Node temp = q.Dequeue();  // Вставити вузол як лівий дочірній елемент батьківського вузла if (temp.left == null) { temp.left = new Node(data);  перерва;  } // Якщо лівий дочірній елемент не є нульовим, помістіть його до черги else q.Enqueue(temp.left);  // Вставити вузол як правий дочірній елемент батьківського вузла if (temp.right == null) { temp.right = new Node(data);  перерва;  } // Якщо правий дочірній елемент не є нульовим, надішліть його до черги else q.Enqueue(temp.right);  } повернути корінь;  } /* функція видалення заданого найглибшого вузла (d_node) у бінарному дереві */ public static void DeleteDeepest(Node root, Node d_node) { Queueq = нова черга();  q.Enqueue(корінь);  // Виконати обхід порядку рівня до останнього вузла Node temp;  while (q.Count != 0) { temp = q.Dequeue();  if (temp == d_node) { temp = null;  d_node = нуль;  повернення;  } if (temp.right != null) { if (temp.right == d_node) { temp.right = null;  d_node = нуль;  повернення;  } else q.Enqueue(temp.right);  } if (temp.left != null) { if (temp.left == d_node) { temp.left = null;  d_node = нуль;  повернення;  } else q.Enqueue(temp.left);  } } } /* функція видалення елемента у бінарному дереві */ public static Node Deletion(Node root, int key) { if (root == null) return null;  if (root.left == null && root.right == null) { if (root.data == ключ) повертає null;  інакше повернути корінь;  }  Чергаq = нова черга();  q.Enqueue(корінь);  Node temp = новий вузол (0);  Вузол key_node = null;  // Виконайте обхід порядку рівня, щоб знайти найглибший вузол (temp) і вузол, який потрібно видалити (key_node) while (q.Count != 0) { temp = q.Dequeue();  if (temp.data == ключ) key_node = temp;  if (temp.left != null) q.Enqueue(temp.left);  if (temp.right != null) q.Enqueue(temp.right);  } if (key_node != null) { int x = temp.data;  key_node.data = x;  DeleteDeepest(root, temp);  } повернути корінь;  } // Обхід дерева за порядком (Ліворуч - Корінь - Праворуч) public static void InorderTraversal(Node root) { if (root == null) return;  InorderTraversal(root.left);  Console.Write(root.data + ' ');  InorderTraversal(root.right);  } // Попередній обхід дерева (корінь - ліворуч - праворуч) public static void PreorderTraversal(Node root) { if (root == null) return;  Console.Write(root.data + ' ');  PreorderTraversal(root.left);  PreorderTraversal(root.right);  } // Обхід дерева постпорядку (Ліворуч - Праворуч - Корінь) public static void PostorderTraversal(Node root) { if (root == null) return;  PostorderTraversal(root.left);  PostorderTraversal(root.right);  Console.Write(root.data + ' ');  } // Функція для обходу дерева порядку рівня public static void LevelorderTraversal(Node root) { if (root == null) return;  // Черга для проходження порядку рівня Чергаq = нова черга();  q.Enqueue(корінь);  while (q.Count != 0) { Node temp = q.Dequeue();  Console.Write(temp.data + ' ');  // Проштовхнути лівого дочірнього елемента в чергу if (temp.left != null) q.Enqueue(temp.left);  // Проштовхнути правий дочірній елемент у чергу if (temp.right != null) q.Enqueue(temp.right);  } } /* Функція драйвера для перевірки наведеного вище алгоритму. */ public static void Main(string[] args) { Node root = null;  // Вставка вузлів root = Insert(root, 10);  корінь = Вставити (корінь, 20);  корінь = Вставити (корінь, 30);  корінь = Вставити (корінь, 40);  Console.Write('Обхід попереднього замовлення: ');  PreorderTraversal(корінь);  Console.Write('
Обхід у порядку: ');  InorderTraversal(корінь);  Console.Write('
Обхід постордера: ');  PostorderTraversal(корінь);  Console.Write('
Обхід порядку рівня: ');  LevelorderTraversal(корінь);  // Видалення вузла з даними = 20 root = Deletion(root, 20);  Console.Write('
Обхід у порядку після видалення: ');  InorderTraversal(корінь);  } }>
Javascript
// Node class to define the structure of the node class Node {  constructor(val) {  this.data = val;  this.left = null;  this.right = null;  } } // Function to insert nodes function insert(root, data) {  // If tree is empty, new node becomes the root  if (root === null) {  root = new Node(data);  return root;  }  // queue to traverse the tree and find the position to  // insert the node  const q = [];  q.push(root);  while (q.length !== 0) {  const temp = q.shift();  // Insert node as the left child of the parent node  if (temp.left === null) {  temp.left = new Node(data);  break;  }  // If the left child is not null push it to the  // queue  else  q.push(temp.left);  // Insert node as the right child of parent node  if (temp.right === null) {  temp.right = new Node(data);  break;  }  // If the right child is not null push it to the  // queue  else  q.push(temp.right);  }  return root; } /* function to delete the given deepest node (d_node) in binary tree */ function deletDeepest(root, d_node) {  const q = [];  q.push(root);  // Do level order traversal until last node  let temp;  while (q.length !== 0) {  temp = q.shift();  if (temp === d_node) {  temp = null;  delete d_node;  return;  }  if (temp.right) {  if (temp.right === d_node) {  temp.right = null;  delete d_node;  return;  }  else  q.push(temp.right);  }  if (temp.left) {  if (temp.left === d_node) {  temp.left = null;  delete d_node;  return;  }  else  q.push(temp.left);  }  } } /* function to delete element in binary tree */ function deletion(root, key) {  if (!root)  return null;  if (root.left === null && root.right === null) {  if (root.data === key)  return null;  else  return root;  }  const q = [];  q.push(root);  let temp;  let key_node = null;  // Do level order traversal to find deepest  // node(temp) and node to be deleted (key_node)  while (q.length !== 0) {  temp = q.shift();  if (temp.data === key)  key_node = temp;  if (temp.left)  q.push(temp.left);  if (temp.right)  q.push(temp.right);  }  if (key_node !== null) {  const x = temp.data;  key_node.data = x;  deletDeepest(root, temp);  }  return root; } // Inorder tree traversal (Left - Root - Right) function inorderTraversal(root) {  if (!root)  return;  inorderTraversal(root.left);  console.log(root.data + ' ');  inorderTraversal(root.right); } // Preorder tree traversal (Root - Left - Right) function preorderTraversal(root) {  if (!root)  return;  console.log(root.data + ' ');  preorderTraversal(root.left);  preorderTraversal(root.right); } // Postorder tree traversal (Left - Right - Root) function postorderTraversal(root) {  if (root === null)  return;  postorderTraversal(root.left);  postorderTraversal(root.right);  console.log(root.data + ' '); } // Function for Level order tree traversal function levelorderTraversal(root) {  if (root === null)  return;  // Queue for level order traversal  const q = [];  q.push(root);  while (q.length !== 0) {  const temp = q.shift();  console.log(temp.data + ' ');  // Push left child in the queue  if (temp.left)  q.push(temp.left);  // Push right child in the queue  if (temp.right)  q.push(temp.right);  } } /* Driver function to check the above algorithm. */ let root = null; // Insertion of nodes root = insert(root, 10); root = insert(root, 20); root = insert(root, 30); root = insert(root, 40); console.log('Preorder traversal: '); preorderTraversal(root); console.log('
Inorder traversal: '); inorderTraversal(root); console.log('
Postorder traversal: '); postorderTraversal(root); console.log('
Level order traversal: '); levelorderTraversal(root); // Delete the node with data = 20 root = deletion(root, 20); console.log('
Inorder traversal after deletion: '); inorderTraversal(root);>
C++14
#include  using namespace std; // Node class to define the structure of the node class Node { public:  int data;  Node *left, *right;  // Parameterized Constructor  Node(int val)  {  data = val;  left = right = NULL;  } }; // Function to insert nodes Node* insert(Node* root, int data) {  // If tree is empty, new node becomes the root  if (root == NULL) {  root = new Node(data);  return root;  }  // queue to traverse the tree and find the position to  // insert the node  queueq;  q.push(корінь);  while (!q.empty()) { Node* temp = q.front();  q.pop();  // Вставити вузол як лівий дочірній елемент батьківського вузла if (temp->left == NULL) { temp->left = new Node(data);  перерва;  } // Якщо лівий дочірній елемент не є null, надішліть його // до черги else q.push(temp->left);  // Вставити вузол як правий дочірній елемент батьківського вузла if (temp->right == NULL) { temp->right = new Node(data);  перерва;  } // Якщо правий дочірній елемент не є null, надішліть його // до черги else q.push(temp->right);  } повернути корінь; } /* функція видалення заданого найглибшого вузла (d_node) у бінарному дереві */ void deletDeepest(Node* root, Node* d_node) { queueq;  q.push(корінь);  // Виконати обхід порядку рівня до останнього вузла Node* temp;  while (!q.empty()) { temp = q.front();  q.pop();  if (temp == d_node) { temp = NULL;  видалити (d_node);  повернення;  } if (temp->right) { if (temp->right == d_node) { temp->right = NULL;  видалити (d_node);  повернення;  } else q.push(temp->right);  } if (temp->left) { if (temp->left == d_node) { temp->left = NULL;  видалити (d_node);  повернення;  } else q.push(temp->left);  } } } /* функція для видалення елемента в бінарному дереві */ Node* deletion(Node* root, int key) { if (!root) return NULL;  if (root->left == NULL && root->right == NULL) { if (root->data == key) return NULL;  інакше повернути корінь;  }  чергаq;  q.push(корінь);  Node* temp;  Node* key_node = NULL;  // Виконайте обхід порядку рівня, щоб знайти // найглибший вузол (temp) і вузол, який потрібно видалити (key_node) while (!q.empty()) { temp = q.front();  q.pop();  if (temp->data == ключ) key_node = temp;  if (temp->left) q.push(temp->left);  if (temp->right) q.push(temp->right);  } if (key_node != NULL) { int x = temp->data;  key_node->data = x;  deletDeepest(root, temp);  } повернути корінь; } // Обхід дерева за порядком (ліворуч - корінь - праворуч) void inorderTraversal(Node* root) { if (!root) return;  inorderTraversal(корінь->ліворуч);  cout<< root->даних<< ' ';  inorderTraversal(root->праворуч); } // Попередній обхід дерева (корінь - ліворуч - праворуч) void preorderTraversal(Node* root) { if (!root) return;  cout<< root->даних<< ' ';  preorderTraversal(root->ліворуч);  preorderTraversal(root->right); } // Обхід дерева Postorder (Ліворуч - Праворуч - Корінь) void postorderTraversal(Node* root) { if (root == NULL) return;  postorderTraversal(корінь->ліворуч);  postorderTraversal(root->right);  cout<< root->даних<< ' '; } // Function for Level order tree traversal void levelorderTraversal(Node* root) {  if (root == NULL)  return;  // Queue for level order traversal  queueq;  q.push(корінь);  while (!q.empty()) { Node* temp = q.front();  q.pop();  cout<< temp->даних<< ' ';  // Push left child in the queue  if (temp->вліво) q.push(temp->left);  // Переміщення правого дочірнього елемента в чергу if (temp->right) q.push(temp->right);  } } /* Функція драйвера для перевірки наведеного вище алгоритму. */ int main() { Node* root = NULL;  // Вставка вузлів root = insert(root, 10);  корінь = вставити (корінь, 20);  корінь = вставити (корінь, 30);  корінь = вставка (корінь, 40);  cout<< 'Preorder traversal: ';  preorderTraversal(root);  cout << '
Inorder traversal: ';  inorderTraversal(root);  cout << '
Postorder traversal: ';  postorderTraversal(root);  cout << '
Level order traversal: ';  levelorderTraversal(root);  // Delete the node with data = 20  root = deletion(root, 20);  cout << '
Inorder traversal after deletion: ';  inorderTraversal(root); }>

Вихід
Preorder traversal: 10 20 40 30 Inorder traversal: 40 20 10 30 Postorder traversal: 40 20 30 10 Level order traversal: 10 20 30 40 Inorder traversal after deletion: 40 10 30>

Аналіз складності операцій з бінарним деревом

Операції Часова складність

Космічна складність

arp - команда
Вставка O(N)

O(N)

Обхід попереднього замовлення O(N)

O(N)

Обхід порядку

O(N)

O(N)

Обхід поштових переказівO(N)

O(N)

Обхід порядку рівняO(N)

O(N)

Видалення

зворотний рядок у java

O(N)

O(N)

Пошук

O(N)

O(N)

Ми можемо використовувати Морріс Траверсал щоб обійти всі вузли бінарного дерева за час O(1).

Переваги бінарного дерева

Недоліки бінарного дерева

Застосування двійкового дерева

Часті запитання щодо бінарного дерева

1. Що таке бінарне дерево?

Двійкове дерево — це нелінійна структура даних, що складається з вузлів, де кожен вузол має не більше двох дочірніх елементів (лівий і правий дочірній).

2. Які бувають типи бінарних дерев?

Бінарні дерева можна класифікувати на різні типи, включаючи повні бінарні дерева, повні бінарні дерева, ідеальні бінарні дерева, збалансовані бінарні дерева (такі як дерева AVL і червоно-чорні дерева) і вироджені (або патологічні) бінарні дерева.

3. Що таке висота бінарного дерева?

Висота бінарного дерева - це довжина найдовшого шляху від кореневого вузла до листкового вузла. Він представляє кількість ребер на найдовшому шляху від кореневого вузла до кінцевого вузла.

лінійний пошук в java

4. Яка глибина вузла у бінарному дереві?

Глибина вузла у бінарному дереві — це довжина шляху від кореневого вузла до цього конкретного вузла. Глибина кореневого вузла дорівнює 0.

5. Як виконати обхід дерева у бінарному дереві?

Обхід дерева у двійковому дереві можна виконати різними способами: обхід у порядку, обхід попереднього замовлення, обхід після замовлення та обхід за рівнем порядку (також відомий як обхід у ширину).

6. Що таке обхід порядку в бінарному дереві?

У Inorder обході вузли рекурсивно відвідуються в такому порядку: лівий дочірній, корінь, правий дочірній. Цей обхід призводить до того, що вузли відвідуються в порядку не спадання в бінарному дереві пошуку.

7. Що таке попередній обхід у бінарному дереві?

У попередньому обході вузли рекурсивно відвідуються в такому порядку: корінь, лівий дочірній, правий дочірній. Цей обхід призводить до того, що кореневий вузол є першим відвідуваним вузлом.

8. Що таке обхід Postorder у бінарному дереві?

У Postorder traversal вузли рекурсивно відвідуються в такому порядку: лівий дочірній, правий дочірній і корінь. Цей обхід призводить до того, що кореневий вузол є останнім відвідуваним вузлом.

9. Яка різниця між бінарним деревом і бінарним деревом пошуку?

Двійкове дерево — це ієрархічна структура даних, де кожен вузол має щонайбільше два дочірніх вузла, тоді як бінарне дерево пошуку — це тип бінарного дерева, у якому лівий дочірній елемент вузла містить значення, менші за значення вузла, а правий дочірній елемент містить значення більше, ніж значення вузла.

10. Що таке збалансоване бінарне дерево?

Збалансоване бінарне дерево — це бінарне дерево, у якому висота лівого та правого піддерев кожного вузла відрізняється щонайбільше на одиницю. Збалансовані дерева допомагають підтримувати ефективні операції, такі як пошук, вставка та видалення з часовими складностями, близькими до O(log n).

Висновок:

Дерево — це ієрархічна структура даних. Основне використання дерев включає підтримку ієрархічних даних, надання помірного доступу та операції вставки/видалення. Бінарні дерева — це окремі випадки дерева, де кожен вузол має не більше двох дочірніх елементів.

Пов'язані статті:

  • Властивості бінарного дерева
  • Типи бінарного дерева