平衡AVL树haskell
我正在Haskell中创建一个AVL树,但我不确定如何平衡该树。我可以添加元素,但它们不平衡。与使用addList方法一样,我在[4,2,1,3,6,8]中添加了如下内容: 布局为:根4(根2(根1为空)(根2为空))(根6为空(根8为空)) 应打印为:平衡AVL树haskell,haskell,avl-tree,Haskell,Avl Tree,我正在Haskell中创建一个AVL树,但我不确定如何平衡该树。我可以添加元素,但它们不平衡。与使用addList方法一样,我在[4,2,1,3,6,8]中添加了如下内容: 布局为:根4(根2(根1为空)(根2为空))(根6为空(根8为空)) 应打印为: 4 2 6 1 3 8 我想平衡一棵树的权利,但不知道如何实现它正确,这是我的代码到目前为止,任何帮助这将是惊人的 data AVLTree a = Empty | Root
4
2 6
1 3 8
我想平衡一棵树的权利,但不知道如何实现它正确,这是我的代码到目前为止,任何帮助这将是惊人的
data AVLTree a = Empty | Root a (AVLTree a) (AVLTree a)
deriving (Eq, Ord, Show)
leaf a = Root a Empty Empty
addNode :: Integral a => a -> AVLTree a -> AVLTree a
addNode a Empty = leaf a
addNode x (Root a left right)
| x > a = Root a left (addNode x right)
| x < a = Root a (addNode x left) right
| otherwise = (Root a left right)
addList :: (Integral a) => [a] -> AVLTree a
addList [] = Empty
addList [n] = leaf n
addList (x:xs) = addNode x (addList xs)
search :: Integral a => AVLTree a -> a -> Bool
search Empty _ = False
search (Root a left right) x
| x == a = True
| x < a = search left x
| x > a = search right x
-- balance :: AVLTree a -> AVLTree a
-- balance Empty = Empty
-- balance tree
-- |(Root r (Root left (Root left1 Empty Empty) Empty) Empty) = (Root left left1 r) -- left left case
-- |(Root r Empty (Root right Empty Empty) (Root right Empty Empty)) = (Root right r right1) -- right right case
-- |(Root r (Root left Empty (Root right Empty Empty)) Empty) = (Root r (Root right (Root left Empty Empty) Empty) Empty) -- left right case
-- |(Root r Empty (Root right (Root left Empty Empty) Empty)) = (Root r Empty (Root left Empty (Root right Empty Empty))) -- right left case
data AVLTree a=空|根a(AVLTree a)(AVLTree a)
推导(Eq、Ord、Show)
叶a=根a空
addNode::Integral a=>a->AVLTree a->AVLTree a
addNode a Empty=叶a
添加节点x(根a左-右)
|x>a=根a左(添加节点x右)
|x[a]->AVLTree a
addList[]=空
addList[n]=叶n
addList(x:xs)=addNode x(addList xs)
搜索::积分a=>AVLTree a->a->Bool
搜索为空uz=False
搜索(根a左-右)x
|x==a=True
|xa=搜索右x
--余额::AVLTree a->AVLTree a
--余额为空
--平衡树
--|(Root r(Root left(Root left1 Empty)Empty)Empty)=(Root left1 r)--左格
--|(Root r Empty(Root right Empty)(Root right Empty))=(Root right r right1)——右格
--|(Root r(Root left Empty(Root right Empty))Empty)=(Root r(Root right(Root left Empty)Empty)Empty)--左右格
--|(Root r Empty(Root right(Root left Empty)Empty))=(Root r Empty(Root left Empty(Root right Empty))右-左大小写
该实现仍然缺少很多内容,您应该多读一些所需内容(即使wikipedia有很好的描述,但如果您进行搜索,也会显示许多其他页面。)
编写任何(自平衡)树最棘手的部分是平衡代码。。。。正如上面所做的那样,在Haskell中创建一棵树非常容易,但是保持搜索日志(N)有点困难。在AVL的情况下,您必须添加更多代码来执行以下操作-
右高-左高
)。如果事情不平衡(即平衡系数1),你必须AVLTree->AVLTree
的操作。直观地说,它将树中的顶部值推到左边(或右边,取决于不平衡的方向),从而恢复平衡。右侧节点将成为新的顶部节点,并将其左侧节点交给旧的顶部节点,然后旧的顶部节点将成为新的左侧节点。这是视觉效果-编辑以回应评论- 您提到的height函数有我上面提到的问题-您正在递归整个树以查找任何节点的高度。插入将不再具有logn复杂性,这就否定了首先拥有一棵树的全部意义。(据我所知,Haskell不会记忆这些值中的任何一个……如果有人知道其他情况,请随意插话,这会简化代码) 更详细地说,您需要像这样扩展AVLTree的定义-
data AVLTree a = Empty | Node a (AVLTree a) (AVLTree a) Int
height (AVLTree _ _ _ height) = height
现在高度就是这样得到的-
data AVLTree a = Empty | Node a (AVLTree a) (AVLTree a) Int
height (AVLTree _ _ _ height) = height
那么你的平衡因子就起作用了-
balanceFactor :: AVLTree a -> Int
balanceFactor Empty = 0
balanceFactor (Root a left right) = (height right) - (height left)
缺点是,更改后,必须添加代码来重新计算整个链到根的高度
然后需要编写另一个函数来检查是否需要旋转,并在需要时应用旋转-
rotateIfNeeded::AVLTree->AVLTree
rotateIfNeeded tree
| b > 1 = fullRotateLeft tree
| b < -1 = fullRotateRight tree
| otherwise = tree
where b = balanceFactor tree
rotateIfNeed::AVLTree->