Какое Самобалансирующееся Дерево является самым простым в Функциональном Программировании? - PullRequest
18 голосов
/ 12 ноября 2010

Я создаю самобалансирующееся дерево в Хаскеле. В качестве упражнения и потому, что это приятно иметь в своей задней руке.

Ранее в C и Python я предпочитал Treaps и Splay Trees из-за их простых правил балансировки. Мне всегда не нравились R / B-деревья, так как они казались мне более трудоемкими, чем стоили.

Теперь, из-за функциональной природы Haskell, вещи, похоже, изменились. Я могу написать функцию вставки R / B в 10 строк кода. Treaps, с другой стороны, требует обертывания для хранения генератора случайных чисел, а Splay Trees - это боль, которую нужно делать сверху вниз.

Итак, я спрашиваю, есть ли у вас опыт работы с другими типами деревьев? Какие из них лучше использовать сопоставление с образцом и нисходящую природу функциональных языков?

Ответы [ 4 ]

8 голосов
/ 03 июня 2011

Хорошо, я думаю, что не было много ссылок или исследований для ответа на этот вопрос.Вместо этого я потратил время, чтобы попробовать ваши разные идеи и деревья.Я не нашел ничего лучше деревьев RB, но, возможно, это просто смещение поиска.

Дерево RB может быть (вставлено) сбалансировано четырьмя простыми правилами, как показано Крисом Окасаки :

balance T (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d)
balance T (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d)
balance T a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d)
balance T a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d)
balance T a x b = T B a x b

Деревья AVL могут быть сбалансированы аналогичным способом сопоставления с образцом.Однако правила также не сжимаются:

balance T (T (T a x b   dx) y c (-1)) z d (-2) = T (T a x b dx) y (T c z d  0) 0
balance T a x (T b y (T c z d   dz)   1 )   2  = T (T a x b  0) y (T c z d dz) 0
balance T (T a x (T b y c   1 )   1 ) z d (-2) = T (T a x b -1) y (T c z d  0) 0
balance T (T a x (T b y c (-1))   1 ) z d (-2) = T (T a x b  0) y (T c z d  1) 0
balance T (T a x (T b y c   _ )   1 ) z d (-2) = T (T a x b  0) y (T c z d  0) 0
balance T a x (T (T b y c   1 ) z d (-1))   2  = T (T a x b -1) y (T c z d  0) 0
balance T a x (T (T b y c (-1)) z d (-1))   2  = T (T a x b  0) y (T c z d  1) 0
balance T a x (T (T b y c   _ ) z d (-1))   2  = T (T a x b  0) y (T c z d  0) 0
balance t = t

Поскольку швы деревьев AVL обычно считаются ниже деревьев RB, они, вероятно, не стоят дополнительных хлопот.

Деревья AA могуттеоретически быть сбалансированным легко и просто:

balance T n (T n a x b) y c = T n a x (T n b y c) -- skew
balance T n a x (T n b y (T n c z d)) = T (n+1) (T n a x b) y (T n c z d) --split
balance T n a x b = T n a x b

Но, к сожалению, Хаскеллу не нравится перегрузка n.Вполне возможно, что менее стандартная реализация деревьев АА, не использующая ранги, но что-то более похожее на R и B., будет работать хорошо.

Splay-деревья сложны, потому что вам нужно сосредоточиться на одном узле, скореечем статическая структура дерева.Это можно сделать с помощью слияния insert и splay .

Treaps также непросто сделать в функциональной среде, поскольку у вас нет глобального генератора случайных чисел, но вам нужно хранить экземпляры вкаждый узел.Это может быть решено с помощью , оставляя задачу генерации приоритетов клиенту , но даже тогда вы не можете выполнить сравнение приоритетов с помощью сопоставления с образцом.

6 голосов
/ 12 ноября 2010

Как вы говорите, Красные Черные деревья не так сложны в использовании.Вы смотрели на пальчики ?Возможно, вам будет интересно дополнить базовую структуру данных чем-то вроде молнии. Еще одно дерево, которое вам может показаться интересным, - AA tree , это упрощение красных черных деревьев.

4 голосов
/ 13 ноября 2010

Это тот, который уже реализован.

В Haskell есть прекрасные реализации сбалансированных деревьев, таких как Data.Map и Data.Set. Разве они не отвечают вашим потребностям? Не переопределять, повторно использовать.

1 голос
/ 13 ноября 2010

Стандартная библиотека OCaml использует дерево AVL для своего map функтора.Кажется, что это проще реализовать, чем RB-дерево, если включить операцию remove.

...