gpt4 book ai didi

haskell - 如何实现最后执行 zig 操作的伸展树(Splay Tree),而不是先执行?

转载 作者:行者123 更新时间:2023-12-04 15:37:43 26 4
gpt4 key购买 nike

对于我的算法和数据结构类(class),我的任务是在 Haskell 中实现一个展开树。我的展开操作算法如下:

  • 如果要展开的节点是根,则返回未更改的树。
  • 如果要展开的节点距根节点只有一层,则执行 zig 操作并返回结果树。
  • 如果要展开的节点距根节点有两层或更多层,则对从该节点开始展开子树的结果执行 zig-zig 或 zig-zag 操作,并返回结果树。

  • 根据我的老师,这是有效的。但是, the Wikipedia description of a splay tree说之字形步骤“将仅作为展开操作的最后一步”,而在我的算法中,它是展开操作的第一步。

    我想实现一个展开树,它最后而不是第一个执行 zig 操作,但我不确定如何最好地完成。在我看来,这样的算法会变得更加复杂,因为在确定是否应该执行 zig 操作之前,需要如何找到要展开的节点。

    如何在 Haskell(或其他一些函数式语言)中实现这一点?

    例子

    在此示例中,我们搜索值 4,提示我们将其展开到树的顶部。

    我的算法(zig作为第一步)

    1 1 4
    \\/
    2 之字形 2 之字形 2
    \-->\------>/\
    3 4 1 3
    \/
    4 3

    维基百科算法(zig 作为最后一步)

    1 1 4
    \\/
    2 之字形 4 之字形 1
    \------>/-->\
    3 3 3
    \//
    4 2 2

    两棵树都是有效的,但它们有不同的结构。我想用函数式语言实现第二个,最好是 Haskell。

    最佳答案

    关键是为要张开的值构建一条路径,然后从底部重建树,如果可能的话,一次两层(这样就可以做出 zig-zip 与 zig-zag 的确定):

    data Tree a = Empty | Node a (Tree a) (Tree a)
    deriving (Eq, Show)

    data Direction = LH | RH
    deriving (Eq, Show)


    splay :: (Ord a) => a -> Tree a -> Tree a
    splay a t = rebuild $ path a t [(undefined,t)]
    where path a Empty ps = ps
    path a n@(Node b l r) ps =
    case compare a b of
    EQ -> ps
    LT -> path a l $ (LH, l) : ps
    GT -> path a r $ (RH, r) : ps

    rebuild :: (Ord a) => [(Direction,Tree a)] -> Tree a
    rebuild ((_,n):[]) = n
    rebuild ((LH,x):(_,p):[]) = zigL x p
    rebuild ((RH,x):(_,p):[]) = zigR x p
    rebuild ((LH,x):(LH,p):(z,g):ps) = rebuild $ (z, zigzigL x p g):ps
    rebuild ((RH,x):(RH,p):(z,g):ps) = rebuild $ (z, zigzigR x p g):ps
    rebuild ((RH,x):(LH,p):(z,g):ps) = rebuild $ (z, zigzagL x p g):ps
    rebuild ((LH,x):(RH,p):(z,g):ps) = rebuild $ (z, zigzagR x p g):ps

    zigL (Node x a b) (Node p _ c) = Node x a (Node p b c)
    zigR (Node x a b) (Node p c _) = Node x (Node p c a) b

    zigzigL (Node x a b) (Node p _ c) (Node g _ d) =
    Node x a (Node p b (Node g c d))

    zigzigR (Node x a b) (Node p c _) (Node g d _) =
    Node x (Node p (Node g d c) a) b

    zigzagL (Node x b c) (Node p a _) (Node g _ d) =
    Node x (Node p a b) (Node g c d)

    zigzagR (Node x b c) (Node p _ a) (Node g d _) =
    Node x (Node g d b) (Node p c a)

    您可以在我的 repo 中找到此代码以及可运行的单元测试和快速检查。 .

    关于haskell - 如何实现最后执行 zig 操作的伸展树(Splay Tree),而不是先执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2861817/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com