[英]What Self Balancing Tree is simplest in Functional Programming?
I'm designing a self balancing tree in Haskell. 我正在Haskell中设计一个自平衡树。 As an exercise and because it is nice to have in your back hand. 作为一项练习,因为你的后背很好。
Previously in C and Python I preferred Treaps and Splay Trees due to their simple balancing rules. 之前在C和Python中,由于其简单的平衡规则,我更喜欢Treaps和Splay Trees。 I always disliked R/B Trees, since they seemed like more work than they were worth. 我总是不喜欢R / B树,因为它们似乎比它们的价值更多的工作。
Now, due to the functional nature of Haskell, things seem to have changed. 现在,由于Haskell的功能性,事情似乎发生了变化。 I can write a R/B insert function in 10 lines of code. 我可以用10行代码编写一个R / B插入函数。 Treaps on the other hand requires wrapping to store the random number generator, and Splay Trees are a pain to do top-down. 另一方面,Treaps需要包装以存储随机数生成器,并且Splay Trees是自上而下的痛苦。
So I'm asking if you have experience with other types of trees? 所以我问你是否有其他类型树木的经验? Which ones are better at utilizing the pattern matching and top-down nature of functional languages? 哪些更好地利用函数式语言的模式匹配和自上而下的性质?
Ok, I guess there wasn't a lot of references or research for answering this question. 好吧,我想没有很多参考或研究来回答这个问题。 Instead I've taken the time to try your different ideas and trees. 相反,我花时间尝试你的不同想法和树木。 I didn't find anything a lot better than RB trees, but perhaps that's just search bias. 我没有找到比RB树更好的东西,但也许这只是搜索偏差。
The RB tree can be (insertion) balanced with four simple rules, as shown by Chris Okasaki : RB树可以(插入)平衡四个简单的规则,如Chris Okasaki所示 :
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 trees can be balanced in a similar pattern matching way. AVL树可以以类似的模式匹配方式进行平衡。 However the rules don't compress as well: 但是规则也不会压缩:
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
As AVL trees seams to generally be considered inferior to RB trees, they are probably not worth the extra hassle. 由于AVL树木接缝通常被认为不如RB树,它们可能不值得额外的麻烦。
AA trees could theoretically be balanced nice and easily by: 从理论上讲,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
But unfortunately Haskell don't like the overloading of n
. 但不幸的是Haskell不喜欢n
的超载。 It is possible that a less standard implementation of AA trees, not using ranks, but something more similar to R and B, would work well. AA树的不太标准的实现,不使用等级,但更类似于R和B,可能会很好。
Splay trees are difficult because you need to focus on a single node, rather than the static structure of the tree. Splay树很难,因为您需要关注单个节点,而不是树的静态结构。 It can be done by merging insert and splay . 它可以通过合并插入和展开来完成。
Treaps are also uneasy to do in a functional environment, as you don't have a global random generator, but need to keep instances in every node. Treaps在功能环境中也很难做,因为您没有全局随机生成器,但需要在每个节点中保留实例。 This can be tackled by leaving the task of generating priorities to the client , but even then, you can't do priority comparison using pattern matching. 这可以通过将生成优先级的任务留给客户端来解决,但即使这样,您也无法使用模式匹配进行优先级比较。
As you say Red Black trees aren't that hard to use. 正如你所说,红黑树并不难以使用。 Have you given finger trees a look ? 你看过手指树了吗? You might be interested in augmenting your base data structure with something like a zipper. 您可能有兴趣使用类似拉链的方式扩充基础数据结构。 Another tree you might find interesting is the AA tree it is a simplification of Red Black Trees. 你可能会觉得有趣的另一棵树是AA树,它是红黑树的简化。
It's the one that's already implemented. 这是已经实施的那个。
There are fine implementations in Haskell of balanced trees such as Data.Map and Data.Set. 在平衡树的Haskell中有很好的实现,例如Data.Map和Data.Set。 Don't they fulfill your needs? 他们不满足你的需求吗? Don't reimplement, reuse. 不要重新实现,重用。
The OCaml standard library uses an AVL tree for its map
functor. OCaml标准库使用AVL树作为其map
仿函数。 It seems as though it's easier to implement than an RB-tree if you include a remove
operation. 如果包含remove
操作,似乎比RB树更容易实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.