logo

Wprowadzenie do drzewa binarnego – samouczki dotyczące struktury danych i algorytmów

Drzewo binarne jest nieliniowa struktura danych gdzie każdy węzeł ma co najwyżej dwoje dzieci. W tym artykule omówimy wszystkie podstawy drzewa binarnego, operacje na drzewie binarnym, jego implementację, zalety i wady, które pomogą Ci rozwiązać wszystkie problemy oparte na drzewie binarnym.

Spis treści



Co to jest drzewo binarne?

Drzewo binarne to a drzewiasta struktura danych (nieliniowa) w którym każdy węzeł może mieć najwyżej dwójkę dzieci które określane są mianem pozostawione dziecko i właściwe dziecko .

Najwyższy węzeł w drzewie binarnym nazywa się źródło i nazywane są węzły położone najniżej liście . Drzewo binarne można sobie wyobrazić jako strukturę hierarchiczną z korzeniem na górze i liśćmi na dole.

Aktorka Sai Pallavi

Reprezentacja drzewa binarnego

Każdy węzeł drzewa binarnego składa się z trzech części:



  • Dane
  • Wskaźnik do lewego dziecka
  • Wskaźnik do odpowiedniego dziecka

Poniżej znajduje się reprezentacja węzła drzewa binarnego w różnych językach:

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; };>
Jawa
// 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;  } }>
Pyton
# 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
>

Rodzaje drzew binarnych

Drzewo binarne można podzielić na typy wielokrotne w oparciu o wiele czynników:



Operacje na drzewie binarnym

1. Wstawienie do drzewa binarnego

Możemy wstawić węzeł w dowolnym miejscu drzewa binarnego, wstawiając go jako lewe lub prawe dziecko dowolnego węzła lub czyniąc węzeł korzeniem drzewa.

Algorytm wstawiania węzła do drzewa binarnego:

  • Sprawdź, czy w drzewie binarnym znajduje się węzeł, w którym brakuje lewego dziecka. Jeśli taki węzeł istnieje, wstaw nowy węzeł jako jego lewe dziecko.
  • Sprawdź, czy w drzewie binarnym znajduje się węzeł, w którym brakuje prawego dziecka. Jeśli taki węzeł istnieje, wstaw nowy węzeł jako jego prawy element podrzędny.
  • Jeśli nie znajdziemy żadnego węzła z brakującym lewym lub prawym dzieckiem, znajdź węzeł, w którym brakuje obu dzieci i wstaw węzeł jako jego lewe lub prawe dziecko.

2. Przechodzenie przez drzewo binarne

Przechodzenie przez drzewo binarne polega na odwiedzeniu wszystkich węzłów drzewa binarnego. Algorytmy przechodzenia przez drzewo można ogólnie podzielić na dwie kategorie:

  • Algorytmy przeszukiwania w głąb (DFS).
  • Algorytmy wyszukiwania wszerz (BFS).

Algorytmy wyszukiwania w głąb (DFS):

  • Przemierzanie w przedsprzedaży (bieżący-lewy-prawy): Odwiedź bieżący węzeł przed odwiedzeniem jakichkolwiek węzłów w lewym lub prawym poddrzewie. Tutaj przejście to korzeń – lewe dziecko – prawe dziecko. Oznacza to, że najpierw przechodzi się przez węzeł główny, potem przez jego lewe dziecko, a na końcu przez prawe dziecko.
  • Przemierzanie porządku (lewy-prąd-prawy): Odwiedź bieżący węzeł po odwiedzeniu wszystkich węzłów w lewym poddrzewie, ale przed odwiedzeniem dowolnego węzła w prawym poddrzewie. Tutaj przejściem jest lewe dziecko – korzeń – prawe dziecko. Oznacza to, że najpierw przechodzi lewe dziecko, potem jego węzeł główny, a na koniec prawe dziecko.
  • Przechodzenie po zamówieniu (lewy-prawy-prąd): Odwiedź bieżący węzeł po odwiedzeniu wszystkich węzłów lewego i prawego poddrzewa. Tutaj przejściem jest lewe dziecko – prawe dziecko – korzeń. Oznacza to, że najpierw przeszło lewe dziecko, potem prawe i na koniec jego węzeł główny.

Algorytmy wyszukiwania wszerz (BFS):

  • Przechodzenie przez kolejność poziomów: Odwiedzaj węzły poziom po poziomie i od lewej do prawej na tym samym poziomie. Tutaj przejście odbywa się na poziomie. Oznacza to, że dziecko znajdujące się najbardziej po lewej stronie przeszło jako pierwsze, a następnie przeszły pozostałe dzieci na tym samym poziomie, od lewej do prawej.

3. Usuwanie w drzewie binarnym

Możemy usunąć dowolny węzeł w drzewie binarnym i zmienić kolejność węzłów po usunięciu, aby ponownie utworzyć prawidłowe drzewo binarne.

Algorytm usuwania węzła w drzewie binarnym:

  • Zaczynając od korzenia, znajdź najgłębszy i najbardziej na prawo położony węzeł w drzewie binarnym oraz węzeł, który chcemy usunąć.
  • Zastąp dane najgłębszego prawego węzła węzłem, który ma zostać usunięty.
  • Następnie usuń najgłębszy węzeł położony skrajnie na prawo.

4. Wyszukiwanie w drzewie binarnym

Elementu w węźle możemy szukać dowolną techniką przechodzenia.

modulacja amplitudy

Algorytm przeszukiwania węzła w drzewie binarnym:

  • Zacznij od węzła głównego.
  • Sprawdź, czy wartość bieżącego węzła jest równa wartości docelowej.
  • Jeśli wartość bieżącego węzła jest równa wartości docelowej, wówczas ten węzeł jest węzłem wymaganym.
  • W przeciwnym razie, jeśli wartość węzła nie jest równa wartości docelowej, rozpocznij wyszukiwanie w lewym i prawym dziecku.
  • Jeśli nie znajdziemy żadnego węzła, którego wartość jest równa target, to tej wartości nie ma w drzewie.

Operacje pomocnicze na drzewie binarnym

Implementacja drzewa binarnego

Poniżej znajduje się kod umożliwiający wstawianie, usuwanie i przeglądanie drzewa binarnego:

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->dane = wartość;  temp->lewo = temp->prawo = NULL;  temperatura powrotu; } // Funkcja wstawiania węzłów Node* wstaw(Node* root, int data) { // Jeśli drzewo jest puste, nowy węzeł staje się korzeniem if (root == NULL) { root = newNode(data);  zwróć korzeń;  } // Kolejka do przejścia przez drzewo i znalezienia miejsca, w którym można wstawić węzeł Node* kolejka[100];  int przód = 0, tył = 0;  kolejka[tył++] = korzeń;  while (przód != tył) { Węzeł* temp = kolejka[przód++];  // Wstaw węzeł jako lewy element podrzędny węzła nadrzędnego if (temp->left == NULL) { temp->left = newNode(data);  przerwa;  } // Jeśli lewe dziecko nie ma wartości null, wepchnij je do kolejki w przeciwnym razie kolejka[rear++] = temp->left;  // Wstaw węzeł jako prawy element podrzędny węzła nadrzędnego if (temp->right == NULL) { temp->right = newNode(data);  przerwa;  } // Jeśli prawe dziecko nie ma wartości null, wepchnij je do kolejki, w przeciwnym razie kolejka[rear++] = temp->right;  } zwróć korzeń; } /* Funkcja usuwająca podany najgłębszy węzeł (d_node) w drzewie binarnym */ void deletDeepest(Node* root, Node* d_node) { Node* kolejka[100];  int przód = 0, tył = 0;  kolejka[tył++] = korzeń;  // Wykonaj przechodzenie w kolejności poziomów aż do ostatniego węzła Node* temp;  while (przód != tył) { temp = kolejka[przód++];  if (temp == d_node) { temp = NULL;  wolny(d_węzeł);  powrót;  } if (temp->right) { if (temp->right == d_node) { temp->right = NULL;  wolny(d_węzeł);  powrót;  } else kolejka[tył++] = temp->prawo;  } if (temp->lewy) { if (temp->lewy == d_node) { temp->lewy = NULL;  wolny(d_węzeł);  powrót;  } else kolejka[tył++] = temp->lewo;  } } } /* Funkcja usuwająca element z drzewa binarnego */ Node* deletion(Node* root, int key) { if (!root) return NULL;  if (root->left == NULL && root->right == NULL) { if (root->data == klucz) return NULL;  w przeciwnym razie zwróć root;  } Węzeł* kolejka[100];  int przód = 0, tył = 0;  kolejka[tył++] = korzeń;  temperatura węzła*;  Węzeł* węzeł_klucza = NULL;  // Wykonaj przechodzenie w kolejności poziomów, aby znaleźć najgłębszy węzeł (temp) i węzeł do usunięcia (key_node) while (front != rear) { temp = kolejka[front++];  if (temp->data == klucz) key_node = temp;  if (temp->lewo) kolejka[tył++] = temp->lewo;  if (temp->prawo) kolejka[tył++] = temp->prawo;  } if (key_node != NULL) { int x = temp->data;  węzeł_klucza->dane = x;  deletDeepest(korzeń, temperatura);  } zwróć korzeń; } // Przechodzenie przez drzewo w kolejności (w lewo - korzeń - w prawo) void inorderTraversal(Node* root) { if (!root) return;  inorderTraversal(root->lewy);  printf('%d ', root->dane);  inorderTraversal(root->right); } // Zamawianie w przedsprzedaży przejścia przez drzewo (Korzeń - Lewo - Prawo) void preorderTraversal(Node* root) { if (!root) return;  printf('%d ', root->dane);  preorderTraversal(root->lewy);  preorderTraversal(root->right); } // Przechodzenie przez drzewo postorderu (Lewo - Prawo - Korzeń) void postorderTraversal(Node* root) { if (root == NULL) return;  postorderTraversal(root->lewy);  postorderTraversal(root->right);  printf('%d ', root->dane); } // Funkcja umożliwiająca przechodzenie przez drzewo kolejności poziomów void poziomorderTraversal(Node* root) { if (root == NULL) return;  // Kolejka do przejścia kolejności poziomów Węzeł* kolejka[100];  int przód = 0, tył = 0;  kolejka[tył++] = korzeń;  while (przód != tył) { Węzeł* temp = kolejka[przód++];  printf('%d ', temp->dane);  // Włóż lewe dziecko do kolejki if (temp->left) kolejka[rear++] = temp->left;  // Włóż prawe dziecko do kolejki if (temp->right) kolejka[rear++] = temp->right;  } } /* Funkcja sterownika sprawdzająca powyższy algorytm. */ int main() { Węzeł* root = NULL;  // Wstawienie węzłów root = wstaw(root, 10);  root = wstaw(korzeń, 20);  root = wstaw(korzeń, 30);  root = wstaw(korzeń, 40);  printf('Przechodzenie w przedsprzedaży: ');  zamówienie w przedsprzedażyTraversal(root);  printf('
Przejście w kolejności: ');  inorderTraversal(root);  printf('
Przechodzenie po zamówieniu: ');  postorderTraversal(root);  printf('
Przechodzenie przez poziom: ');  LevelorderTraversal(root);  // Usuń węzeł z danymi = 20 root = deletion(root, 20);  printf('
Przejście w kolejności po usunięciu: ');  inorderTraversal(root);  zwróć 0; }>
Jawa
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 = nowa lista połączona();  q.oferta(root);  while (!q.isEmpty()) { Temp. węzła = q.poll();  // Wstaw węzeł jako lewy element podrzędny węzła nadrzędnego if (temp.left == null) { temp.left = new Node(data);  przerwa;  } // Jeśli lewe dziecko nie ma wartości null, włóż je do // kolejki, w przeciwnym razie q.offer(temp.left);  // Wstaw węzeł jako prawy element podrzędny węzła nadrzędnego if (temp.right == null) { temp.right = new Node(data);  przerwa;  } // Jeśli właściwe dziecko nie ma wartości null, włóż je do // kolejki, w przeciwnym razie q.offer(temp.right);  } zwróć korzeń;  } /* funkcja usuwająca podany najgłębszy węzeł (d_node) w drzewie binarnym */ public static void deletDeepest(Node root, Node d_node) { Queueq = nowa lista połączona();  q.oferta(root);  // Wykonaj przechodzenie na poziomie aż do ostatniego węzła Temp. węzła;  while (!q.isEmpty()) { temp = q.poll();  if (temp == d_node) { temp = null;  d_node = null;  powrót;  } if (temp.right != null) { if (temp.right == d_node) { temp.right = null;  d_node = null;  powrót;  } else q.offer(temp.right);  } if (temp.left != null) { if (temp.left == d_node) { temp.left = null;  d_node = null;  powrót;  } else q.offer(temp.left);  } } } /* funkcja usuwająca element z drzewa binarnego */ public static Usuwanie węzła (korzeń węzła, klucz int) { if (root == null) return null;  if (root.left == null && root.right == null) { if (root.data == klucz) return null;  w przeciwnym razie zwróć root;  }  Kolejkaq = nowa lista połączona();  q.oferta(root);  Temperatura węzła = nowy węzeł (0);  Węzeł klucz_node = null;  // Wykonaj przechodzenie w kolejności poziomów, aby znaleźć najgłębszy // węzeł (temp) i węzeł do usunięcia (key_node) while (!q.isEmpty()) { temp = q.poll();  if (temp.data == klucz) 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;  węzeł_klucza.dane = x;  deletDeepest(korzeń, temperatura);  } zwróć korzeń;  } // Przechodzenie przez drzewo w kolejności (Lewo - Korzeń - Prawo) public static void inorderTraversal(Node root) { if (root == null) return;  inorderTraversal(root.left);  System.out.print(root.data + ' ');  inorderTraversal(root.right);  } // Zamówienie przejścia drzewa w przedsprzedaży (Korzeń - Lewy - Prawy) public static void preorderTraversal(Korzeń węzła) { if (root == null) return;  System.out.print(root.data + ' ');  zamówienie w przedsprzedażyTraversal(root.left);  zamówienie w przedsprzedażyTraversal(root.right);  } // Przechodzenie przez drzewo postorderu (Lewo - Prawo - Korzeń) public static void postorderTraversal(Korzeń węzła) { if (root == null) return;  postorderTraversal(root.left);  postorderTraversal(root.right);  System.out.print(root.data + ' ');  } // Funkcja przechodzenia przez drzewo kolejności poziomów public static void poziomorderTraversal(Node root) { if (root == null) return;  // Kolejka do przejścia kolejności poziomów Kolejkaq = nowa lista połączona();  q.oferta(root);  while (!q.isEmpty()) { Temp. węzła = q.poll();  System.out.print(temp.dane + ' ');  // Włóż lewe dziecko do kolejki if (temp.left != null) q.offer(temp.left);  // Wciśnij prawe dziecko w kolejkę if (temp.right != null) q.offer(temp.right);  } } /* Funkcja sterownika sprawdzająca powyższy algorytm. */ public static void main(String[] args) { Korzeń węzła = null;  // Wstawienie węzłów root = wstaw(root, 10);  root = wstaw(korzeń, 20);  root = wstaw(korzeń, 30);  root = wstaw(korzeń, 40);  System.out.print('Przechodzenie w przedsprzedaży: ');  zamówienie w przedsprzedażyTraversal(root);  System.out.print('
Przejście w kolejności: ');  inorderTraversal(root);  System.out.print('
Przechodzenie po zamówieniu: ');  postorderTraversal(root);  System.out.print('
Przechodzenie przez poziom: ');  LevelorderTraversal(root);  // Usuń węzeł z danymi = 20 root = deletion(root, 20);  System.out.print('
Przejście w kolejności po usunięciu: ');  inorderTraversal(root);  } }>
Pyton
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 = nowa kolejka();  q.Kolejkuj(root);  while (q.Count != 0) { Temp. węzła = q.Dequeue();  // Wstaw węzeł jako lewy element podrzędny węzła nadrzędnego if (temp.left == null) { temp.left = new Node(data);  przerwa;  } // Jeśli lewe dziecko nie ma wartości null, włóż je do kolejki w przeciwnym razie q.Enqueue(temp.left);  // Wstaw węzeł jako prawy element podrzędny węzła nadrzędnego if (temp.right == null) { temp.right = new Node(data);  przerwa;  } // Jeśli właściwe dziecko nie ma wartości null, włóż je do kolejki w przeciwnym razie q.Enqueue(temp.right);  } zwróć korzeń;  } /* funkcja usuwająca podany najgłębszy węzeł (d_node) w drzewie binarnym */ public static void DeleteDeepest(Node root, Node d_node) { Queueq = nowa kolejka();  q.Kolejkuj(root);  // Wykonaj przechodzenie na poziomie aż do ostatniego węzła Temp. węzła;  póki (q.Count!= 0) { temp = q.Dequeue();  if (temp == d_node) { temp = null;  d_node = null;  powrót;  } if (temp.right != null) { if (temp.right == d_node) { temp.right = null;  d_node = null;  powrót;  } else q.Enqueue(temp.right);  } if (temp.left != null) { if (temp.left == d_node) { temp.left = null;  d_node = null;  powrót;  } else q.Enqueue(temp.left);  } } } /* funkcja usuwająca element z drzewa binarnego */ public static Node Deletion(root węzła, int klucz) { if (root == null) return null;  if (root.left == null && root.right == null) { if (root.data == klucz) return null;  w przeciwnym razie zwróć root;  }  Kolejkaq = nowa kolejka();  q.Kolejkuj(root);  Temperatura węzła = nowy węzeł (0);  Węzeł klucz_node = null;  // Wykonaj przechodzenie w kolejności poziomów, aby znaleźć najgłębszy węzeł (temp) i węzeł do usunięcia (key_node) while (q.Count != 0) { temp = q.Dequeue();  if (temp.data == klucz) 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;  węzeł_klucza.dane = x;  DeleteDeepest(root, temp);  } zwróć korzeń;  } // Przechodzenie przez drzewo Inorder (Lewo – Korzeń – Prawo) public static void InorderTraversal(Node root) { if (root == null) return;  InorderTraversal(root.left);  Console.Write(root.data + ' ');  InorderTraversal(root.right);  } // Zamówienie przejścia drzewa w przedsprzedaży (Korzeń - Lewy - Prawy) public static void PreorderTraversal(Korzeń węzła) { if (root == null) return;  Console.Write(root.data + ' ');  PrzedsprzedażTraversal(root.left);  PreorderTraversal(root.right);  } // Przechodzenie przez drzewo postorderu (Lewo - Prawo - Korzeń) public static void PostorderTraversal(Korzeń węzła) { if (root == null) return;  PostorderTraversal(root.left);  PostorderTraversal(root.right);  Console.Write(root.data + ' ');  } // Funkcja przechodzenia przez drzewo kolejności poziomów public static void LevelorderTraversal(Root węzła) { if (root == null) return;  // Kolejka do przejścia kolejności poziomów Kolejkaq = nowa kolejka();  q.Kolejkuj(root);  while (q.Count != 0) { Temp. węzła = q.Dequeue();  Console.Write(temp.data + ' ');  // Włóż lewe dziecko do kolejki if (temp.left != null) q.Enqueue(temp.left);  // Włóż prawe dziecko do kolejki if (temp.right != null) q.Enqueue(temp.right);  } } /* Funkcja sterownika sprawdzająca powyższy algorytm. */ public static void Main(string[] args) { Korzeń węzła = null;  // Wstawienie węzłów root = Insert(root, 10);  root = wstaw(korzeń, 20);  root = wstaw(korzeń, 30);  root = wstaw(korzeń, 40);  Console.Write('Przeglądanie zamówienia w przedsprzedaży: ');  Zamów w przedsprzedażyTraversal(root);  Console.Write('
Przechodzenie w kolejności: ');  InorderTraversal(root);  Console.Write('
Przechodzenie po zamówieniu: ');  PostorderTraversal(root);  Console.Write('
Przechodzenie przez kolejność poziomów: ');  LevelorderTraversal(root);  // Usuń węzeł z danymi = 20 root = Deletion(root, 20);  Console.Write('
Przechodzenie w kolejności po usunięciu: ');  InorderTraversal(root);  } }>
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(root);  while (!q.empty()) { Węzeł* temp = q.front();  q.pop();  // Wstaw węzeł jako lewy element podrzędny węzła nadrzędnego if (temp->left == NULL) { temp->left = new Node(data);  przerwa;  } // Jeśli lewe dziecko nie ma wartości null, włóż je do // kolejki, w przeciwnym razie q.push(temp->left);  // Wstaw węzeł jako prawy element podrzędny węzła nadrzędnego if (temp->right == NULL) { temp->right = new Node(data);  przerwa;  } // Jeśli właściwe dziecko nie ma wartości null, włóż je do // kolejki, w przeciwnym razie q.push(temp->right);  } zwróć korzeń; } /* funkcja usuwająca podany najgłębszy węzeł (d_node) w drzewie binarnym */ void deletDeepest(Node* root, Node* d_node) { kolejkaQ;  q.push(root);  // Wykonaj przechodzenie w kolejności poziomów aż do ostatniego węzła Node* temp;  while (!q.empty()) { temp = q.front();  q.pop();  if (temp == d_node) { temp = NULL;  usuń (d_node);  powrót;  } if (temp->right) { if (temp->right == d_node) { temp->right = NULL;  usuń (d_node);  powrót;  } else q.push(temp->right);  } if (temp->lewy) { if (temp->lewy == d_node) { temp->lewy = NULL;  usuń (d_node);  powrót;  } else q.push(temp->left);  } } } /* funkcja usuwająca element z drzewa binarnego */ Node* deletion(Node* root, int key) { if (!root) return NULL;  if (root->left == NULL && root->right == NULL) { if (root->data == klucz) return NULL;  w przeciwnym razie zwróć root;  }  kolejkaQ;  q.push(root);  temperatura węzła*;  Węzeł* węzeł_klucza = NULL;  // Wykonaj przechodzenie poziomów, aby znaleźć najgłębszy // węzeł (temp) i węzeł do usunięcia (key_node) while (!q.empty()) { temp = q.front();  q.pop();  if (temp->data == klucz) key_node = temp;  if (temp->lewo) q.push(temp->lewo);  if (temp->prawo) q.push(temp->prawo);  } if (key_node != NULL) { int x = temp->dane;  węzeł_klucza->dane = x;  deletDeepest(korzeń, temperatura);  } zwróć korzeń; } // Przechodzenie przez drzewo w kolejności (w lewo - korzeń - w prawo) void inorderTraversal(Node* root) { if (!root) return;  inorderTraversal(root->lewy);  cout<< root->dane<< ' ';  inorderTraversal(root->Prawidłowy); } // Zamawianie w przedsprzedaży przejścia przez drzewo (Korzeń - Lewo - Prawo) void preorderTraversal(Node* root) { if (!root) return;  cout<< root->dane<< ' ';  preorderTraversal(root->lewy);  preorderTraversal(root->right); } // Przechodzenie przez drzewo postorderu (Lewo - Prawo - Korzeń) void postorderTraversal(Node* root) { if (root == NULL) return;  postorderTraversal(root->lewy);  postorderTraversal(root->right);  cout<< root->dane<< ' '; } // Function for Level order tree traversal void levelorderTraversal(Node* root) {  if (root == NULL)  return;  // Queue for level order traversal  queueQ;  q.push(root);  while (!q.empty()) { Węzeł* temp = q.front();  q.pop();  cout<< temp->dane<< ' ';  // Push left child in the queue  if (temp->lewy) q.push(temp->lewy);  // Wciśnij prawe dziecko w kolejkę if (temp->right) q.push(temp->right);  } } /* Funkcja sterownika sprawdzająca powyższy algorytm. */ int main() { Węzeł* root = NULL;  // Wstawienie węzłów root = wstaw(root, 10);  root = wstaw(korzeń, 20);  root = wstaw(korzeń, 30);  root = wstaw(korzeń, 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); }>

Wyjście
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>

Analiza złożoności operacji na drzewie binarnym

Operacje Złożoność czasu

Złożoność przestrzeni

Wprowadzenie NA)

NA)

Zamów w przedsprzedaży NA)

NA)

Przeprawa nieuporządkowana

NA)

NA)

Przesyłka pocztowaNA)

NA)

Przechodzenie przez poziom zamówieniaNA)

NA)

Usunięcie

cienki algorytm

NA)

NA)

Badawczy

NA)

NA)

Możemy użyć Przejście Morrisa przejść przez wszystkie węzły drzewa binarnego w czasie O(1).

Zalety drzewa binarnego

Wady drzewa binarnego

Zastosowania drzewa binarnego

Często zadawane pytania dotyczące drzewa binarnego

1. Co to jest drzewo binarne?

Drzewo binarne to nieliniowa struktura danych składająca się z węzłów, z których każdy ma co najwyżej dwoje dzieci (lewe i prawe dziecko).

2. Jakie są rodzaje drzew binarnych?

Drzewa binarne można podzielić na różne typy, w tym pełne drzewa binarne, kompletne drzewa binarne, doskonałe drzewa binarne, zrównoważone drzewa binarne (takie jak drzewa AVL i drzewa czerwono-czarne) oraz zdegenerowane (lub patologiczne) drzewa binarne.

ciąg Java do tablicy

3. Jaka jest wysokość drzewa binarnego?

Wysokość drzewa binarnego to długość najdłuższej ścieżki od węzła głównego do węzła liścia. Reprezentuje liczbę krawędzi na najdłuższej ścieżce od węzła głównego do węzła liścia.

4. Jaka jest głębokość węzła w drzewie binarnym?

Głębokość węzła w drzewie binarnym to długość ścieżki od węzła głównego do tego konkretnego węzła. Głębokość węzła głównego wynosi 0.

5. Jak wykonać przechodzenie przez drzewo binarne?

Przechodzenie przez drzewo binarne można wykonać na różne sposoby: przechodzenie w kolejności, przechodzenie w kolejności przed zamówieniem, przechodzenie po zamówieniu i przechodzenie w kolejności poziomów (znane również jako przechodzenie wszerz).

6. Co to jest przejście Inorder w drzewie binarnym?

W przechodzeniu Inorder węzły są odwiedzane rekurencyjnie w następującej kolejności: lewe dziecko, korzeń, prawe dziecko. To przechodzenie powoduje, że węzły są odwiedzane w niemalejącej kolejności w drzewie wyszukiwania binarnego.

7. Co to jest przeglądanie zamówienia w przedsprzedaży w drzewie binarnym?

W przypadku przeglądania w przedsprzedaży węzły są odwiedzane rekurencyjnie w następującej kolejności: korzeń, lewe dziecko, prawe dziecko. To przejście powoduje, że węzeł główny jest pierwszym odwiedzanym węzłem.

8. Co to jest przechodzenie postordera w drzewie binarnym?

W trybie Postorder węzły są odwiedzane rekurencyjnie w następującej kolejności: lewe dziecko, prawe dziecko i korzeń. To przejście powoduje, że węzeł główny jest ostatnim węzłem odwiedzanym.

9. Jaka jest różnica pomiędzy drzewem binarnym a drzewem wyszukiwania binarnego?

Drzewo binarne to hierarchiczna struktura danych, w której każdy węzeł ma co najwyżej dwoje dzieci, podczas gdy drzewo poszukiwań binarnych to rodzaj drzewa binarnego, w którym lewe dziecko węzła zawiera wartości mniejsze niż wartość węzła, a prawe dziecko zawiera wartości większa niż wartość węzła.

10. Co to jest zrównoważone drzewo binarne?

Zrównoważone drzewo binarne to drzewo binarne, w którym wysokość lewego i prawego poddrzewa każdego węzła różni się co najwyżej o jeden. Zrównoważone drzewa pomagają w utrzymaniu wydajnych operacji, takich jak wyszukiwanie, wstawianie i usuwanie, przy złożoności czasowej bliskiej O (log n).

Wniosek:

Drzewo jest hierarchiczną strukturą danych. Główne zastosowania drzew obejmują utrzymywanie danych hierarchicznych, zapewnianie umiarkowanego dostępu oraz operacje wstawiania/usuwania. Drzewa binarne to szczególne przypadki drzew, w których każdy węzeł ma co najwyżej dwoje dzieci.

Powiązane artykuły:

  • Właściwości drzewa binarnego
  • Rodzaje drzew binarnych