Какими основными свойствами обладает бинарное дерево поиска (Binary Search Tree — BST)?

Ответ

Бинарное дерево поиска (BST) — это упорядоченная древовидная структура данных со следующими ключевыми свойствами:

1. Структурное свойство:

  • Каждый узел имеет не более двух потомков: левого и правого.

2. Свойство упорядоченности (главное свойство):

  • Для любого узла X:
    • Все значения в левом поддереве узла X меньше значения самого узла X.
    • Все значения в правом поддереве узла X больше или равны значению узла X (зависит от реализации, допускающей дубликаты).
  • Это свойство должно выполняться рекурсивно для всех поддеревьев.

3. Следствия свойств (операции):

  • Поиск, вставка, удаление в сбалансированном BST выполняются в среднем за O(log n), где n — количество узлов.
  • Обход inorder (левый-узел-правый) посещает узлы в отсортированном порядке.

Визуализация и пример кода:

        8
       / 
      3   10
     /     
    1   6    14
       /    /
      4   7 13

Пример реализации поиска в BST на Java:

class Node {
    int key;
    Node left, right;
    public Node(int item) { key = item; }
}

public class BinarySearchTree {
    Node root;

    // Рекурсивный поиск ключа
    Node search(Node root, int key) {
        // Базовый случай: узел пуст или ключ найден
        if (root == null || root.key == key) {
            return root;
        }
        // Ключ меньше значения корня -> ищем в левом поддереве
        if (key < root.key) {
            return search(root.left, key);
        }
        // Ключ больше -> ищем в правом поддереве
        return search(root.right, key);
    }
}

Важное предупреждение о производительности: В худшем случае (например, когда элементы добавляются в отсортированном порядке: 1, 2, 3, 4...), дерево вырождается в связный список, и сложность операций падает до O(n). Для гарантированной логарифмической сложности используются самобалансирующиеся деревья (AVL, Красно-черные).

Ответ 18+ 🔞

А, слушай, вот эта ваша бинарная хуйня, дерево поиска... Ну, в общем, представь себе, как будто ты — царь, а вокруг тебя — два подчинённых, левый и правый. И ты им строго настрого наказал: «Левый, все твои значения должны быть меньше моего! Правый, все твои — больше! А то в пизду отправлю!»

И вот, блядь, главный принцип, на котором всё держится:

  1. Структура. У каждого узла максимум два отпрыска — левый и правый. Никаких оргий, всё чинно.
  2. Порядок. Это святое, ёпта! Для любого узла Х: всё, что слева от него — меньше него самого. Всё, что справа — больше (или равно, если ты такой распиздяй, который дубликаты разрешает). И этот закон, блядь, работает рекурсивно для всей ихней иерархии! То есть левый подчиненный тоже кричит своим: «Вы все меньше меня, суки!», и так до самого низа.

Что из этого вытекает, блядь? Ну, если дерево не кривое, то найти, вставить или удалить узел можно в среднем за O(log n). Это быстро, как хуй с горы. А если пройтись по нему «inorder» (слева-узел-справа), то значения вылезут уже отсортированные, красота!

Вот, смотри, как это выглядит, на картинке для дебилов:

        8
       / 
      3   10
     /     
    1   6    14
       /    /
      4   7 13

Видишь? У восьмёрки слева всё меньше (3,1,6,4,7), справа всё больше (10,14,13). И у тройки то же самое: слева 1, справа 6. Порядок, блядь!

А вот кусок кода, как искать, чтоб ты не тупил:

class Node {
    int key;
    Node left, right;
    public Node(int item) { key = item; }
}

public class BinarySearchTree {
    Node root;

    // Рекурсивный поиск ключа
    Node search(Node root, int key) {
        // Базовый случай: узел пуст или ключ найден
        if (root == null || root.key == key) {
            return root;
        }
        // Ключ меньше значения корня -> ищем в левом поддереве
        if (key < root.key) {
            return search(root.left, key);
        }
        // Ключ больше -> ищем в правом поддереве
        return search(root.right, key);
    }
}

НО! Вот тут-то и собака зарыта, сука! Есть один пиздецкий нюанс. Если ты, мудак, будешь вставлять элементы по порядку (1, потом 2, потом 3, потом 4...), то что получится? А получится, что у единицы правый сын — двойка, у двойки правый сын — тройка, и так далее. И твоё красивое дерево превратится в обычный связный список, ёбаный в рот! И сложность операций скатится с O(log n) до O(n), то есть до полного пиздеца.

Поэтому умные дядьки придумали самобалансирующиеся деревья (AVL, красно-чёрные). Они, блядь, как хитрая жопа, постоянно себя подкручивают, чтобы не выродиться. Но это уже совсем другая, ебать, история.