Что такое двоичное дерево поиска (Binary Search Tree, BST)

Ответ

Двоичное дерево поиска (BST) — это древовидная структура данных на основе узлов, где каждый узел имеет не более двух дочерних элементов (левого и правого потомка).

Главное его предназначение — быстрый поиск, вставка и удаление элементов.

Ключевые свойства

Для любого узла N в дереве должны выполняться следующие условия:

  1. Все значения в левом поддереве узла N меньше, чем значение в N.
  2. Все значения в правом поддереве узла N больше, чем значение в N.
  3. Оба — левое и правое — поддеревья также являются двоичными деревьями поиска.

Производительность

Благодаря этим свойствам, операции поиска, вставки и удаления в сбалансированном дереве выполняются в среднем за логарифмическое время O(log n).

  • Средний случай: O(log n)
  • Худший случай: O(n). Происходит, когда дерево вырождается в связный список (например, при последовательной вставке отсортированных элементов).

Пример реализации на Python

# Класс для представления узла дерева
class Node:
    def __init__(self, key):
        self.left = None
        self.right = None
        self.val = key

# Функция для поиска значения в дереве
def search(root, key):
    # Базовые случаи: корень пуст или ключ найден
    if root is None or root.val == key:
        return root

    # Ключ больше значения в корне -> ищем в правом поддереве
    if root.val < key:
        return search(root.right, key)

    # Ключ меньше значения в корне -> ищем в левом поддереве
    return search(root.left, key)

Для решения проблемы худшего случая используют самобалансирующиеся деревья, такие как АВЛ-деревья или Красно-чёрные деревья.

Ответ 18+ 🔞

А, ну это про эти ваши деревья, где всё по полочкам разложено, как в хорошем бардаке, только с правилами! Двоичное дерево поиска, блядь — представь себе начальника-мажора, который сидит посередине, а всё, что левее него, должно быть тупее, а всё, что правее — умнее. И так на каждом этаже, ёпта!

Смысл-то в чём, а? Чтобы искать, добавлять и выкидывать элементы быстрее, чем я успеваю сказать «в рот меня чих-пых». Если дерево не кривое, как моя жизненная дорога, то все операции — за логарифмическое время, O(log n). Красота!

А вот если вставлять тупо по порядку, 1, 2, 3, 4... то получится не дерево, а длиннющая верёвка из узлов, похуй на ветвление. И тогда поиск превратится в тупой перебор, O(n), будто ты в односвязном списке ищешь свою потерянную совесть. Полный пиздец, короче.

Чтобы такого не было, умные дядьки придумали самобалансирующиеся штуки — АВЛ-деревья, красно-чёрные... Они там сами себя подкручивают, как гайки, чтобы не завалиться на бок. Но это уже высший пилотаж, ёперный театр.

Смотри, как просто искать значение в коде:

# Класс для представления узла дерева
class Node:
    def __init__(self, key):
        self.left = None
        self.right = None
        self.val = key

# Функция для поиска значения в дереве
def search(root, key):
    # Базовые случаи: корень пуст или ключ найден
    if root is None or root.val == key:
        return root

    # Ключ больше значения в корне -> ищем в правом поддереве
    if root.val < key:
        return search(root.right, key)

    # Ключ меньше значения в корне -> ищем в левом поддереве
    return search(root.left, key)

Вот и вся магия. Пришёл, посмотрел на корень — не твоё? Ну и иди нахуй... то есть, в соответствующее поддерево. Либо налево, если ты меньше, либо направо, если больше. Рекурсия, блядь, делает всё за тебя. Главное — чтобы дерево было приличное, а не как мои планы на понедельник.