Шаг 172.
Основы языка Haskell. Рекурсивные типы данных. Красно-чёрные деревья, AA-деревья. Реализация красно-чёрных деревьев на языке Haskell

    На этом шаге мы приведем ряд положений, которыми будем пользоваться при построении дерева.

    Красно-чёрное бинарное дерево поиска описательно представим так:

    (Корень(Цвет) Левое_поддерево Правое_поддерево).

    Для моделирования этого представления в языке Haskell воспользуемся тернарным функтором

   (Node root left right),
где root - корень дерева, а left и right соответственно - левое и правое поддерево. Пустое дерево зададим функтором NIL.

    Таким образом, определение типа данных "целочисленное красно-чёрное бинарное дерево поиска" в языке Haskell, поддерживающего класс типов Eq, над которыми определены отношения равенства, будет таким:

   data RBTree = NIL (Char)
               | Node (Integer,Char) (RBTree) (RBTree)
      deriving Eq

    Узел дерева будем обозначать парой

   (Integer,Char),
первый элемент которой обозначает ключ узла (число), а второй элемент - цвет узла (красный - 'R' или чёрный - 'B').

    Внешние узлы дерева (или NIL-узлы) будем обозначать парой

   (NIL ('B')),
т.к. цвет их является чёрным.

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

   (NIL ('B')).

    Базовые функции лежащие в основе построения красно-чёрного бинарного дерева поиска Tree с NIL-узлами:

    Основные функции для построения красно-чёрных деревьев:

  1. Вставка узла в красно-чёрное дерево:
       rb_Ins:: RBTree -> Integer -> RBTree
       rb_Ins tree s
    

        Функция rb_Ins вызывает функцию rb_Ins1

       rb_Ins1:: RBTree -> Integer -> RBTree
       rb_Ins1 tree s
    

        Функция rb_Ins1 анализирует и исправляет нарушения красно-чёрных свойств дерева tree, если таковы имеются, после вставки в него красного узла s с помощью функции addTree:

       addTree:: Integer -> Char -> RBTree -> RBTree
       addTree s color tree
    

        Затем функция rb_Ins перекрашивает корень полученного дерева в чёрный цвет;

  2. Удаление узла из красно-чёрного дерева:
       rb_Del:: RBTree -> Integer -> RBTree
       rb_Del tree s
    

        Функция rb_Del анализирует дерево и применяет к нему, если возможно, функцию delete, удаляющую заданный узел s из красно-чёрного дерева tree:

       delete:: Integer -> RBTree -> RBTree
       delete s tree
    

        Если полученное дерево имеет нарушения красно-чёрных свойств, то оно поступает на вход функции rb_Del1:

       rb_Del1:: RBTree -> Integer -> RBTree
       rb_Del1 tree x
    

        Функция rb_Del1 восстанавливает красно-чёрные свойства дерева.

    Вспомогательные предикаты для реализации основных функций:

  1. Установление вхождения элемента s в красно-чёрное бинарное дерево поиска tree с NIL-узлами:
       srch:: Integer -> RBTree -> Bool
       srch s tree
    
  2. Установление наличия вершины "дедушка" для заданной вершины s красно-чёрного бинарного дерева поиска tree с NIL-узлами:
       pSrch_G:: Integer -> RBTree -> Bool
       pSrch_G s tree
    
  3. Установление наличия вершины "отец" для заданной вершины s красно-чёрного бинарного дерева поиска tree с NIL-узлами:
       pSrch_D:: Integer -> RBTree -> Bool
       pSrch_D s tree
    
  4. Установление наличия вершины "брат" для заданной вершины s красно-чёрного бинарного дерева поиска tree с NIL-узлами:
       pSrch_B:: Integer -> RBTree -> Bool
       pSrch_B s tree
    
  5. Установление наличия вершины "племянник" (слева) для заданной вершины s красно-чёрного бинарного дерева поиска tree с NIL-узлами:
       pSrch_Nl:: Integer -> RBTree -> Bool
       pSrch_Nl s tree
    
  6. Установление наличия вершины "племянник" (справа) для заданной вершины s красно-чёрного бинарного дерева поиска tree с NIL-узлами:
       pSrch_Nr:: Integer -> RBTree -> Bool
       pSrch_Nr s tree
    
  7. установление наличия вершины "дядя" для заданной вершины s красно-чёрного бинарного дерева поиска tree с NIL-узлами:
       pSrch_U:: Integer -> RBTree -> Bool
       pSrch_U s tree
    

    Вспомогательные функции для реализации основных функций:

  1. Определение поддерева красно-чёрного бинарного дерева поиска tree с корнем s (при отсутствии узла s возвращается пустое дерево):
       search:: Integer -> RBTree -> RBTree
       search s tree
    
  2. Определение узла "дедушка" красно-чёрного бинарного дерева поиска tree с ключом s:
       srch_G:: Integer -> RBTree -> (Integer,Char)
       srch_G s tree
    
  3. Определение узла "отец" красно-чёрного бинарного дерева поиска tree с ключом s:
       srch_D:: Integer -> RBTree -> (Integer,Char)
       srch_D s tree
    
  4. Определение узла "брат" красно-чёрного бинарного дерева поиска tree с ключом s:
       srch_B:: Integer -> RBTree -> (Integer,Char)
       srch_B s tree
    
  5. Определение узла "племянник" (слева) красно-чёрного бинарного дерева поиска tree с ключом s:
       srch_Nl:: Integer -> RBTree -> (Integer,Char)
       srch_Nl s tree
    
  6. Определение узла "племянник" (справа) красно-чёрного бинарного дерева поиска tree с ключом s:
       srch_Nr:: Integer -> RBTree -> (Integer,Char)
       srch_Nr s tree
    
  7. Определение узла "дядя" красно-чёрного бинарного дерева поиска tree с ключом s:
       srch_U:: Integer -> RBTree -> (Integer,Char)
       srch_U s tree
    
  8. Замена всех вхождений узла a на узел b красно-чёрного дерева поиска tree:
       subst:: RBTree -> (Integer,Char) -> (Integer,Char) -> RBTree
       subst tree a b
    
  9. Изменение цвета узла с указанным ключом v на заданный цвет clr_V в красно-чёрном бинарном дереве поиска tree:
       chng_Clr:: RBTree -> Integer -> Char -> RBTree
       chng_Clr tree v clr_V
    
  10. Dыполнение операции "ротация вправо" в красно-чёрном бинарном дереве поиска tree:
       rot_Right:: RBTree -> RBTree
       rot_Right tree
    
  11. Выполнение операции "ротация влево" в красно-чёрном бинарном дереве поиска tree:
       rot_Left:: RBTree -> RBTree
       rot_Left tree
    
  12. Выполнение операции ротации, производимой над частью красно-чёрного бинарного дерева поиска tree, поднимая узел с указанным ключом s на уровень выше:
       rotInTree:: Integer -> RBTree -> RBTree
       rotInTree s tree
    
  13. Изображение красно-чёрного бинарного дерева поиска tree на экране дисплея:
       outTree:: RBTree -> IO()
       outTree tree
    
  14. Изображение красно-чёрного бинарного дерева поиска tree на экране дисплея в виде строки описания дерева (l - накапливающий параметр, значение которого при первоначальном обращении равно 0):
       drawTree:: RBTree -> Int -> String
       drawTree tree l
    

    На следующем шаге мы рассмотрим демонстрационные примеры.




Предыдущий шаг Содержание Следующий шаг