Ответ
Бинарное дерево поиска (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+ 🔞
А, слушай, вот эта ваша бинарная хуйня, дерево поиска... Ну, в общем, представь себе, как будто ты — царь, а вокруг тебя — два подчинённых, левый и правый. И ты им строго настрого наказал: «Левый, все твои значения должны быть меньше моего! Правый, все твои — больше! А то в пизду отправлю!»
И вот, блядь, главный принцип, на котором всё держится:
- Структура. У каждого узла максимум два отпрыска — левый и правый. Никаких оргий, всё чинно.
- Порядок. Это святое, ёпта! Для любого узла Х: всё, что слева от него — меньше него самого. Всё, что справа — больше (или равно, если ты такой распиздяй, который дубликаты разрешает). И этот закон, блядь, работает рекурсивно для всей ихней иерархии! То есть левый подчиненный тоже кричит своим: «Вы все меньше меня, суки!», и так до самого низа.
Что из этого вытекает, блядь? Ну, если дерево не кривое, то найти, вставить или удалить узел можно в среднем за 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, красно-чёрные). Они, блядь, как хитрая жопа, постоянно себя подкручивают, чтобы не выродиться. Но это уже совсем другая, ебать, история.