На какой структуре данных основана реализация TreeMap в Java?

Ответ

Красно-черное дерево (Red-Black Tree) — самобалансирующееся бинарное дерево поиска.

Основные свойства, обеспечивающие балансировку (O(log n) для put/get/remove):

  1. Каждый узел имеет цвет: красный или черный.
  2. Корень всегда черный.
  3. Все листья (NIL) считаются черными.
  4. Красный узел не может иметь красного потомка (нет двух красных узлов подряд).
  5. Все простые пути от узла до его листьев содержат одинаковое количество черных узлов (одинаковая черная высота).

Пример использования:

TreeMap<Integer, String> map = new TreeMap<>();
map.put(3, "Three");
map.put(1, "One");
map.put(2, "Two");
// Элементы автоматически сортируются по ключу (естественный порядок)
System.out.println(map); // {1=One, 2=Two, 3=Three}
// Навигационные методы
Integer lowerKey = map.lowerKey(2); // 1
Integer higherKey = map.higherKey(2); // 3

Ключи должны быть сравнимы (реализовывать Comparable) или в конструктор необходимо передать Comparator.

Ответ 18+ 🔞

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

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

Вот их пять заповедей, нарушать которые низя:

  1. Узел может быть либо красным, либо черным. Как светофор, блядь.
  2. Корень — всегда чёрный папа. С него всё начинается, авторитет, блядь.
  3. Все листья (пустые места, NIL) — тоже считаются чёрными. Просто договорились так.
  4. Главное правило, ёбта! Красный узел не может породить красного ребёнка. Два красных подряд — это пиздец, нарушение баланса. Красные должны быть разделены чёрными, как ссорящиеся родственники на свадьбе.
  5. От любого узла до каждого его листа должно быть одинаковое число чёрных узлов на пути. Это называется «чёрная высота» и она везде одинаковая, вот в чём весь фокус!

Когда ты добавляешь или удаляешь узел, эти правила могут ебнуться. Тогда дерево начинает крутить себя само: повороты и перекрашивания. Оно тыкает узлы, меняет цвета, чтобы снова всё стало по правилам. Выглядит сложно, но оно просто не хочет, чтобы его поиск превратился в долгую пиздёжку.

Где это, блядь, применяется? Да прямо в Java, в TreeMap! Смотри, как просто:

TreeMap<Integer, String> map = new TreeMap<>();
map.put(3, "Три");
map.put(1, "Один");
map.put(2, "Два");
// Внутри эта бандура автоматом всё в красно-чёрное дерево упаковывает и сортирует по ключам!
System.out.println(map); // {1=Один, 2=Два, 3=Три}
// А ещё там навигация готовая, чтоб не ебаться
Integer ключПоменьше = map.lowerKey(2); // 1
Integer ключПобольше = map.higherKey(2); // 3

Только смотри, чувак: ключи должны уметь сравниваться. Либо они сами по себе сравнимы (как Integer), либо ты суёшь в конструктор свой Comparator, а то дерево нихуя не поймёт, что больше, а что меньше. В общем, штука мощная, вся соль — в этих пяти правилах, которые не дают дереву превратиться в кривую палку.