Вставка
Щоб вставити вузол, ми спочатку шукаємо в дереві місце, куди його варто додати. Новий вузол завжди додається як аркуш, тому обоє його нащадка є NIL-вузлами й передбачаються чорними. Після вставки красимо вузол у червоні кольори. Після цього дивимося на предка й перевіряємо, чи не порушується червоно-чорна властивість. Якщо необхідно, ми перефарбовуємо вузол і робимо поворот, щоб збалансувати дерево.
Вставивши червоний вузол, ми зберігаємо властивість чорної висоти (властивість 4). Однак, при цьому може виявитися порушеним властивість 3. Ця властивість полягає в тому, що обоє нащадка червоного вузла обов'язково чорні. У нашому випадку обоє нащадка нового вузла чорні по визначенню (оскільки вони є NIL-вузлами), так що розглянемо ситуацію, коли предок нового вузла червоний: при цьому буде порушена властивість 3. Досить розглянути наступні два випадки:
Кожне коректування, вироблене при вставці вузла, змушує нас здійнятися в дереві на один крок. У цьому випадку до зупинки алгоритму буде зроблене 1 обертання (2, якщо вузол був правим нащадком). Метод видалення аналогічний.
Рис. 0.6: Вставка – Червоний предок, червоний “дядько”
Рис. 0.7: Вставка – червоний предок, чорний “дядько”
Реалізація
Реалізація роботи із червоно-чорними деревами на Си перебуває в розділі 4.7. Оператори typedef T, а також порівнюють compLT і compEQ варто змінити так, щоб вони відповідали даним, збереженим у вузлах дерева. У кожному вузлі Node зберігаються покажчики left, right на двох нащадків і parent на предка. Кольори вузла зберігається в поле color і може бути або RED, або BLACK. Властиво дані зберігаються в поле data. Всі листи дерева є “сторожовими” (sentinel), що сильно спрощує коди. Вузол root є коренем дерева й на самому початку є сторожовим.
Функція insertNode запитує пам'ять під новий вузол, установлює потрібні значення його полий і вставляє в дерево. Відповідно, вона викликає insertFixup, що стежить за збереженням червоно-чорних властивостей. Функція deleteNode видаляє вузол з дерева. Вона викликає deleteFixup, що відновлює червоно-чорні властивості. Функція findNode шукає в дереві потрібний вузол.
Розділені списки – це зв'язні списки, які дозволяють вам стрибнути (skip) до потрібного елемента. Це дозволяє перебороти обмеження послідовного пошуку, що є основним джерелом неефективного пошуку в списках. У той же час вставка й видалення залишаються порівняно ефективними. Оцінка середнього часу пошуку в таких списках є O(lg n). Для найгіршого випадку оцінкою є O(n), але гірший випадок украй малоймовірний. Відмінне введення в розділені списки ви знайдете в П'ю [5].
Теорія
Ідея, що лежить в основі розділених списків, дуже нагадує метод, використовуваний при пошуку імен в адресній книжці. Щоб знайти ім'я, ви позначаєте буквою сторінку, звідки починаються імена, що починаються із цієї букви. На мал. 3.8, наприклад, самий верхній список представляє звичайний однозв'язний список. Додавши один “рівень” посилань, ми прискоримо пошук. Спочатку ми підемо по посиланнях рівня 1, потім, коли дійдемо по потрібного відрізка списку, підемо по посиланнях нульового рівня.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.