Бинарные деревья

Материал из m6a
Перейти к: навигация, поиск

Бинарное дерево — это иерархическая структура данных, в которой каждый узел имеет не более двух потомков, называемых левым потомком (left child) и правым потомком (right child). Бинарные деревья широко используются в информатике для организации и хранения данных, а также для реализации различных алгоритмов.

Основные понятия

  1. Узел (Node): Основной элемент бинарного дерева, содержащий данные и ссылки на левого и правого потомков.
  2. Корень (Root): Верхний узел дерева, не имеющий предков.
  3. Лист (Leaf): Узел, не имеющий потомков.
  4. Родитель (Parent): Узел, имеющий потомков.
  5. Потомок (Child): Узел, являющийся потомком другого узла (родителя).
  6. Левый потомок (Left Child): Узел, являющийся левым потомком другого узла.
  7. Правый потомок (Right Child): Узел, являющийся правым потомком другого узла.
  8. Поддерево (Subtree): Дерево, состоящее из узла и всех его потомков.
  9. Глубина узла (Depth): Количество ребер от корня до узла.
  10. Высота узла (Height): Количество ребер от узла до самого дальнего листа в его поддереве.
  11. Высота дерева (Height): Высота корня дерева.

Свойства бинарных деревьев

  1. Максимальное количество узлов на уровне: На уровне $i$ (где корень находится на уровне 0) может быть не более $2^i$ узлов.
  2. Максимальное количество узлов в дереве высоты h: В бинарном дереве высоты $h$ может быть не более $2^{h+1} - 1$ узлов.
  3. Минимальная высота бинарного дерева с n узлами: Минимальная высота бинарного дерева с $n$ узлами равна $\lceil \log_2(n+1) \rceil - 1$, где $\lceil x \rceil$ — наименьшее целое число, большее или равное $x$.
  4. Полное бинарное дерево (Full Binary Tree): Бинарное дерево, в котором каждый узел, кроме листьев, имеет ровно двух потомков.
  5. Совершенное бинарное дерево (Perfect Binary Tree): Полное бинарное дерево, в котором все листья находятся на одном и том же уровне.
  6. Сбалансированное бинарное дерево (Balanced Binary Tree): Бинарное дерево, в котором высота левого и правого поддеревьев каждого узла отличается не более чем на 1. Примерами сбалансированных бинарных деревьев являются AVL-деревья и красно-черные деревья.

Типы бинарных деревьев

  1. Полное бинарное дерево (Full Binary Tree): Каждый узел имеет 0 или 2 потомка.
  2. Совершенное бинарное дерево (Perfect Binary Tree): Все внутренние узлы имеют 2 потомка и все листья находятся на одном уровне.
  3. Сбалансированное бинарное дерево (Balanced Binary Tree): Высота дерева минимальна и разница высот поддеревьев каждого узла не превышает 1.

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

Бинарное дерево можно реализовать с использованием узлов и ссылок (указателей) на левого и правого потомков.

Пример реализации узла бинарного дерева на Python:

```python class Node:

   def __init__(self, data):
       self.data = data
       self.left = None
       self.right = None

```

Пример реализации бинарного дерева на Python:

```python class BinaryTree:

   def __init__(self, root):
       self.root = Node(root)

```

Операции над бинарными деревьями

  1. Вставка узла (Insert): Добавление нового узла в дерево.
  2. Удаление узла (Delete): Удаление узла из дерева.
  3. Поиск узла (Search): Поиск узла с заданным значением в дереве.
  4. Обход дерева (Traversal): Посещение всех узлов дерева в определенном порядке.
  5. Определение высоты дерева (Height): Вычисление высоты дерева.
  6. Определение размера дерева (Size): Вычисление количества узлов в дереве.

Обходы бинарных деревьев

Существуют различные способы обхода бинарных деревьев, которые отличаются порядком посещения узлов:

  1. Прямой обход (Preorder Traversal):
    1. Посещение корня, затем левого поддерева, затем правого поддерева.
    2. Алгоритм:
      1. 1. Посетить корень.
      2. 2. Рекурсивно обойти левое поддерево.
      3. 3. Рекурсивно обойти правое поддерево.
  2. Центрированный обход (Inorder Traversal):
    1. Посещение левого поддерева, затем корня, затем правого поддерева.
    2. Алгоритм:
      1. 1. Рекурсивно обойти левое поддерево.
      2. 2. Посетить корень.
      3. 3. Рекурсивно обойти правое поддерево.
  3. Обратный обход (Postorder Traversal):
    1. Посещение левого поддерева, затем правого поддерева, затем корня.
    2. Алгоритм:
      1. 1. Рекурсивно обойти левое поддерево.
      2. 2. Рекурсивно обойти правое поддерево.
      3. 3. Посетить корень.
  4. Обход в ширину (Level Order Traversal):
    1. Посещение узлов по уровням, начиная с корня.
    2. Алгоритм:
      1. 1. Посетить корень.
      2. 2. Добавить левого и правого потомков корня в очередь.
      3. 3. Пока очередь не пуста:
        1. a. Удалить узел из начала очереди.
        2. b. Посетить удаленный узел.
        3. c. Добавить левого и правого потомков удаленного узла в очередь.

Пример реализации обходов бинарного дерева на Python:

```python class Node:

   def __init__(self, data):
       self.data = data
       self.left = None
       self.right = None

def preorder_traversal(node):

   if node:
       print(node.data, end=" ")
       preorder_traversal(node.left)
       preorder_traversal(node.right)

def inorder_traversal(node):

   if node:
       inorder_traversal(node.left)
       print(node.data, end=" ")
       inorder_traversal(node.right)

def postorder_traversal(node):

   if node:
       postorder_traversal(node.left)
       postorder_traversal(node.right)
       print(node.data, end=" ")

def levelorder_traversal(root):

   if root is None:
       return
   queue = [root]
   while queue:
       node = queue.pop(0)
       print(node.data, end=" ")
       if node.left:
           queue.append(node.left)
       if node.right:
           queue.append(node.right)

```

Применение бинарных деревьев

Бинарные деревья используются в широком спектре приложений, включая:

  1. Поиск и сортировка данных: Бинарные деревья поиска (BST) используются для эффективного хранения и поиска данных.
  2. Реализация других структур данных: Бинарные деревья используются для реализации других структур данных, таких как кучи (heaps) и хеш-таблицы (hash tables).
  3. Сжатие данных: Деревья Хаффмана используются для сжатия данных без потерь.
  4. Маршрутизация в сетях: Бинарные деревья используются для организации маршрутизации в сетях.
  5. Компиляторы: Бинарные деревья используются для представления синтаксических деревьев в компиляторах.

Примеры использования бинарных деревьев

  1. Бинарное дерево поиска (BST):
    1. Бинарное дерево, в котором для каждого узла все ключи в левом поддереве меньше ключа в этом узле, а все ключи в правом поддереве больше ключа в этом узле.
  1. Дерево Хаффмана:
    1. Используется для сжатия данных путем присвоения более коротким кодам наиболее часто встречающимся символам.

Преимущества и недостатки использования бинарных деревьев

Преимущества:

  1. Эффективный поиск, вставка и удаление элементов (в сбалансированных бинарных деревьях поиска): В сбалансированных бинарных деревьях поиска эти операции выполняются за логарифмическое время $O(\log n)$.
  2. Удобное представление иерархических данных: Бинарные деревья позволяют удобно представлять иерархические данные.
  3. Широкий спектр применения: Бинарные деревья используются в различных областях программирования.

Недостатки:

  1. Несбалансированные деревья могут приводить к низкой производительности: В несбалансированных бинарных деревьях поиска операции поиска, вставки и удаления элементов могут выполняться за линейное время $O(n)$.
  2. Дополнительные затраты памяти на хранение указателей: Для каждого элемента дерева необходимо хранить указатели на левого и правого потомков, что увеличивает потребление памяти.

Понимание бинарных деревьев и умение их эффективно использовать является важным для разработки качественного и производительного программного обеспечения.