Красно-черное дерево на Си
Красно-черное дерево - это самобалансирующееся бинарное дерево поиска, которое гарантирует логарифмическую высоту дерева и эффективные операции вставки, удаления и поиска.
Вот пример реализации красно-черного дерева на языке Си:
#include <stdio.h> #include <stdlib.h> // Определение цвета узла typedef enum { RED, BLACK } Color; // Структура узла красно-черного дерева typedef struct Node { int data; Color color; struct Node *left, *right, *parent; } Node; // Создание нового узла Node* createNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->color = RED; // Новый узел всегда красный newNode->left = newNode->right = newNode->parent = NULL; return newNode; } // Вспомогательная функция для левого поворота void leftRotate(Node **root, Node *x) { Node *y = x->right; x->right = y->left; if (y->left != NULL) y->left->parent = x; y->parent = x->parent; if (x->parent == NULL) *root = y; else if (x == x->parent->left) x->parent->left = y; else x->parent->right = y; y->left = x; x->parent = y; } // Вспомогательная функция для правого поворота void rightRotate(Node **root, Node *y) { Node *x = y->left; y->left = x->right; if (x->right != NULL) x->right->parent = y; x->parent = y->parent; if (y->parent == NULL) *root = x; else if (y == y->parent->left) y->parent->left = x; else y->parent->right = x; x->right = y; y->parent = x; } // Функция для восстановления свойств красно-черного дерева после вставки void fixInsert(Node **root, Node *z) { while (z != *root && z->parent->color == RED) { if (z->parent == z->parent->parent->left) { Node *y = z->parent->parent->right; if (y != NULL && y->color == RED) { // Дядя красный - случай 1 z->parent->color = BLACK; y->color = BLACK; z->parent->parent->color = RED; z = z->parent->parent; } else { if (z == z->parent->right) { // Дядя черный и z - правый ребенок - случай 2 z = z->parent; leftRotate(root, z); } // Дядя черный и z - левый ребенок - случай 3 z->parent->color = BLACK; z->parent->parent->color = RED; rightRotate(root, z->parent->parent); } } else { // Симметричный случай Node *y = z->parent->parent->left; if (y != NULL && y->color == RED) { z->parent->color = BLACK; y->color = BLACK; z->parent->parent->color = RED; z = z->parent->parent; } else { if (z == z->parent->left) { z = z->parent; rightRotate(root, z); } z->parent->color = BLACK; z->parent->parent->color = RED; leftRotate(root, z->parent->parent); } } } (*root)->color = BLACK; // Корень всегда черный } // Вставка узла в красно-черное дерево void insert(Node **root, int data) { Node *z = createNode(data); Node *y = NULL; Node *x = *root; // Обычная вставка в бинарное дерево поиска while (x != NULL) { y = x; if (z->data < x->data) x = x->left; else x = x->right; } z->parent = y; if (y == NULL) *root = z; else if (z->data < y->data) y->left = z; else y->right = z; // Восстановление свойств красно-черного дерева fixInsert(root, z); } // Вспомогательная функция для вывода дерева (обход в порядке in-order) void inOrder(Node *root) { if (root == NULL) return; inOrder(root->left); printf("%d(%s) ", root->data, root->color == RED ? "RED" : "BLACK"); inOrder(root->right); } // Основная функция для демонстрации int main() { Node *root = NULL; // Вставка элементов insert(&root, 10); insert(&root, 20); insert(&root, 30); insert(&root, 15); insert(&root, 25); insert(&root, 5); insert(&root, 35); // Вывод дерева printf("In-order traversal of the constructed tree:\n"); inOrder(root); printf("\n"); return 0; }
Объяснение кода:
Структура узла: Каждый узел содержит данные, цвет (красный или черный), указатели на левого и правого потомков, а также на родителя.
Вращения:
leftRotateиrightRotate- операции, которые помогают сохранять баланс дерева.
Вставка:
Сначала выполняется стандартная вставка как в бинарное дерево поиска.
Затем вызывается
fixInsertдля восстановления свойств красно-черного дерева.
Восстановление свойств (
fixInsert):Исправляет возможные нарушения свойств красно-черного дерева после вставки.
Рассматривает три основных случая в зависимости от цвета дяди текущего узла.
Свойства красно-черного дерева:
Каждый узел либо красный, либо черный.
Корень всегда черный.
Все листья (NIL) черные.
У красного узла оба потомка черные.
Все пути от узла до его листьев содержат одинаковое количество черных узлов.
Этот код демонстрирует базовые операции красно-черного дерева. Для полной реализации нужно также добавить функции удаления узла и обработки других случаев балансировки.
Комментариев нет:
Отправить комментарий