ГоловнаСтаттіАлгоритми

Червоно-чорні дерева: Балансування без підрахунку

П’ять колірних правил обмежують кожен шлях від кореня до листка на коефіцієнт двох — не потрібне поле висоти.

mysimulator teamОновлено — червень 2026≈ 8 хв читання▶ Відкрити симуляцію

П’ять незмінних величин, що обмежують висоту

Червоно-чорне дерево — це бінарне пошукове дерево, де кожен вузол має бути розфарбований червоним або чорним, і дотримуються чотири додаткові правила — поряд із звичайним упорядкуванням BST:

1. Кожен вузол є червоним або чорним. 2. Корінь – чорний. 3. Будь-яке листове дерево (NIL / null) вважається чорним. 4. Червоний вузол не має червоного дитини (немає двох червоних у рядку на жодному шляху). 5. Для будь-якого заданого вузла кожен шлях від нього до будь-яких його листових вузлів-NULL проходить через однакову кількість чорних вузлів — "чорну висоту" цього вузла.

Жоден з цих правил не згадує висоту безпосередньо, що є ключем: замість відстеження та ребалансування за точним числом висоти (як у AVL-дереві), червоно-чорне дерево забезпечує локальний колірний обмежений, який дешево перевіряється та дешево виправляється після одного вставлення або видалення, і це обмеження випадково передбачає глобальне обмеження висоти.

1. Every node is red or black.
2. The root is black.
3. Every leaf (NIL / null) is considered black.
4. A red node never has a red child (no two reds in a row on any path).
5. Every path from a given node to any of its descendant NIL leaves
   passes through the same number of black nodes — the node's "black-height".

Почему высота остается O(log n)

Правило 4 гласит, что в строке нельзя иметь двух красных узлов подряд, поэтому на любом пути от корня к листу не более чем каждые другие узлы будут красными. Это означает, что общая длина пути не превышает дважды его черного уровня. Правило 5 утверждает, что все пути от корня имеют один и тот же черный уровень bh. Поддерево с черным уровнем bh содержит как минимум 2^bh − 1 внутренних узлов (чистая индукция: удвоение черного уровня как минимум удваивает количество узлов, поскольку оба ребенка черного узла имеют черный уровень bh−1 или bh). Объединяя это:

n >= 2^bh - 1 (n = количество внутренних узлов) => bh <= log2(n + 1) => высота <= 2 * bh <= 2 * log2(n + 1) Таким образом, независимо от того, в каком порядке вставляются или удаляются ключи, самая длинная возможная длина пути от корня до листа никогда не превышает примерно дважды наименьшую, и обе они равны O(log n). Поиск, вставка и удаление все проходят по не более чем одному пути от корня до листа, поэтому все три случаются в худшем случае O(log n) — та же асимптотическая гарантия, что и для идеально сбалансированного дерева, при меньшей стоимости перебалансировки.

n >= 2^bh - 1        (n = number of internal nodes)
=> bh <= log2(n + 1)
=> height <= 2 * bh <= 2 * log2(n + 1)

Повороти та перефарбовування при вставці

Новий вузол завжди фарбується в червоний колір спочатку (це ніколи не порушує правила чорного рівня, оскільки він не додає жодних чорних вузлів до будь-якого шляху) і потім виконується процедура виправлення, яка йде вгору, виправляючи будь-які порушення червоного-червоного, які вона спричинила. Виправлення має дві дуже різні особистості залежно від кольору родича нового вузла (брата батька:)

родич є ЧЕРВОНИМ: перефарбуйте батька та родича в чорний колір, перефарбуйте бабусю в червоний колір, потім продовжуйте виправлення, починаючи з бабусі (може розгортатися до кореня) родич є ЧОРНИМ (або відсутній): 1-2 дерева обертання (випади LL, LR, RL або RR) плюс перефарбування, яке виправляє порушення локально в O(1) обертаннях — не потрібно додаткового розгортання live demo · inserting keys and watching rotations keep it balanced● LIVE Випадок лише перефарбування може, в принципі, поширитися на всі шляхи до кореня, але кожен випадок обертання негайно припиняє виправлення, що пояснює, чому вставка все ще коштує O(1) середніх обертів, незважаючи на те, що перефарбування ланцюга є O(log n) у найгіршому випадку.

uncle is RED:
  recolour parent and uncle black, grandparent red,
  then continue fixing up from the grandparent (may cascade to the root)

uncle is BLACK (or missing):
  1-2 tree rotations (LL, LR, RL or RR case) plus a recolour,
  which fixes the violation locally in O(1) rotations — no further
  cascading is needed
жива демонстрація · пов'язана симуляція● LIVE

Видалення вузла, що виявляється чорним, може знизити чорний рівень одного піддерева нижче його братів, створюючи "дворазову чорну" дефіцит, який потрібно вирішити шляхом більш тривалого аналізу випадку, ніж вставку — класична реалізація має чотири окремі випадки кольору братів, кожна з яких має свій рецепт обертання та перефарбування. Це єдина причина, чому реалізації червоного-чорного дерева відомі своєю складністю у розробці з нуля, і чому більшість виробничого коду звертається до добре протестованої реалізації бібліотеки замість написання її з нуля.

Deleting a node that turns out to be black can drop the black-height of one subtree below its siblings, creating a "double-black" deficiency that has to be pushed upward and resolved through a longer case analysis than insertion needs — the classic implementation has four distinct sibling-colour cases, each with its own rotation and recolour recipe. It is the single reason red-black tree implementations are notoriously fiddly to get right from scratch, and why most production code reaches for a well-tested library implementation rather than writing one from memory.

Где це фактично використовується

C++'s std::map і std::set є, в кожному основному стандартному забезпеченні реалізації, біло-червоними деревами. TreeMap і TreeSet Java також такі. Linux kernel's Completely Fair Scheduler підтримує виконувані процеси у біло-червоному дереві, відсортованому за віртуальним часом виконання, тому обидва вибирати наступний процес для запуску та повторно вставляти процес після його запуску є операціями O(log n) на дереві, яке залишається збалансованим під непередбачуваним, високочастотним потоком вставлення та видалень — саме робоче навантаження, для якого оптимізовані біло-червоні дерева.

Frequently asked questions

Чому не використовувати просто бінарне дерево пошуку?

Просте BST не має гарантії балансу. Якщо вставляти ключі в відсортованому порядку, воно деградує до зв’язаного списку, з пошуком, вставкою та видаленням O(n) замість O(log n). Червоно-чорне дерево витрачає трохи додаткових обчислень на кожну вставку та видалення, щоб запобігти цьому деградації, гарантуючи, що висота ніколи не перевищує приблизно 2·log2(n+1) незалежно від порядку вставки.

Чи є червоно-чорні дерева ідеально збалансованими?

Ні, і це навмисно. Ідеально збалансоване дерево, таке як AVL, підтримує два піддерева на кожному вузлі в межах 1 за висотою, що забезпечує швидші пошуки, але вимагає більше обертань при вставці та видаленні. Червоно-чорне дерево гарантує лише те, що найдовший шлях від кореня до листового вузла не перевищує удвічі найкоротший, що є більш м’яким обмеженням, але потребує менше операцій ребалансування, роблячи його швидшим для навантажень з частими записами.

Де використовуються червоно-чорні дерева насправді?

Стандартна бібліотека C++ реалізує std::map та std::set як червоно-чорні дерева, так само як TreeMap та TreeSet у Java. Повністю справедливий планувальник ядра Linux використовує червоно-чорне дерево, відсортоване за віртуальним часом виконання, щоб вибрати наступний процес для запуску з O(log n), а також багато інтервальних дерев баз даних та мов програмування будуються на основі червоно-чорного дерева.

Спробуйте наживо

Усе, що вище, працює прямо у вашому браузері — відкрийте Red-Black Trees і змінюйте параметри під час роботи. Нічого не встановлюється, нічого не завантажується на сервер, уся модель живе в одній вкладці.

▶ Відкрити симуляцію Red-Black Trees

Що ви знайшли?

Додати кроки відтворення (опційно)