简体   繁体   English

haskell二叉树函数

[英]haskell binary tree function

I have to write a function in haskell that checks if two binary trees are mirror images of one another. 我必须在haskell中编写一个函数,以检查两个二叉树是否互为镜像。 This is what i have so far but i do not know if the True && areMirrorImages l1 r2 && areMirrorImages r1 l2 is the right way to do it. 这是我到目前为止所拥有的,但是我不知道True && areMirrorImages l1 r2 && areMirrorImages r1 l2是否是正确的方法。 I was trying to logical AND True with the results of recursively calling the areMirrorImages functions. 我试图通过递归调用areMirrorImages函数的结果进行逻辑“与”运算。

-- Tests whether two BinaryTrees are mirror images of one another
areMirrorImages :: (Eq (BinaryTree a), Eq a) => BinaryTree a -> BinaryTree a -> Bool
areMirrorImages Empty Empty = True
areMirrorImages _ Empty = False
areMirrorImages Empty _     = False
areMirrorImages (Node x1 left1 right1) (Node x2 left2 right2) = 
    if (x1 == x2 && left1 == right2 && right1 == left2)
then True && (areMirrorImages left1 right2) && (areMirrorImages right1 left2)
else False 

This is the error i get when i try to compile: 这是我尝试编译时遇到的错误:

A2.hs:2:0:
    Non-type variables, or repeated type variables,
      in the constraint: Eq (BinaryTree a)
    (Use -fglasgow-exts to permit this)
    In the type signature:
      areMirrorImages :: (Eq (BinaryTree a), Eq a) =>
                         BinaryTree a -> BinaryTree a -> Bool

I cant seem to figure out what's wrong 我似乎无法找出问题所在

Requiring Eq (BinaryTree a) means that you need to compare (test for Eq uality) two trees. 要求Eq (BinaryTree a)意味着您需要比较(测试Eq品质)两棵树。 You don't need to do this because you are testing to see if trees are mirrors of each other, not if they are equal. 您不需要执行此操作,因为您正在测试以查看树是否是彼此的镜像,而不是是否相等。

When are trees mirrors of each other? 树木何时互为镜子? When the key is the same and when the opposite branches are mirror images of each other. 当键相同且相对的分支彼此互为镜像时。

The key is the same: x1 == x2 关键是相同的: x1 == x2

Opposite branches are mirror images: areMirrorImages left1 right2 && areMirrorImages right1 left2 相反的分支是镜像: areMirrorImages left1 right2 && areMirrorImages right1 left2

Translate that into Haskell: 将其翻译为Haskell:

areMirrorImages (Node x1 left1 right1) (Node x2 left2 right2) = 
    x1 == x2 && areMirrorImages left1 right2 && areMirrorImages right1 left2

Haskell allows you to write concise, straightforward code. Haskell使您可以编写简洁明了的代码。 There is no need for using if then else . if then else没有,则无需使用。

Probably the only constraint you need is Eq a, if BinaryTree has a derived instance of Eq. 如果BinaryTree具有Eq的派生实例,则可能唯一需要的约束是Eq a。 That derived instance will look something like: 该派生实例将类似于:

instance Eq a => Eq (BinaryTree a) where
    ...

Therefore, knowing that a can be compared for equality will allow Haskell to figure out that your BinaryTree a values can be compared for equality. 因此,知道可以将a进行相等性比较将使Haskell能够确定您的BinaryTree a值可以进行相等性进行比较。

Your logic also looks like it might be wrong to me. 您的逻辑也似乎对我来说是错误的。 Your function will return False unless both left1 == right2 and areMirrorImages left1 right2 are True, for example. 你的函数将返回False,除非双方 left1 == right2areMirrorImages left1 right2是真实的,例如。 These cannot both be true unless left1 and right2 are symmetrical, assuming a correct implementation of areMirrorImages. 除非left1和right2是对称的(假设areMirrorImages正确实现),否则它们都不能为真。

You've got the right idea. 您有正确的主意。 I've trimmed your version down a little bit and it seems to work just fine: 我已经将您的版本缩小了一点,看来一切正常:

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

areMirrorImages :: (Eq a) => BinaryTree a -> BinaryTree a -> Bool
areMirrorImages (Node x1 left1 right1) (Node x2 left2 right2) 
    | x1 == x2  = areMirrorImages left1 right2 &&
                  areMirrorImages right1 left2
    | otherwise = False
areMirrorImages Empty Empty = True
areMirrorImages _ _ = False

So what did I change? 那我改变了什么?

The type signature - In the end, you only really need to invoke == on the elements of the tree, so only a needs to be an instance of Eq . 该类型签名 -在最后,你才真正需要调用树的元素==,所以只有a需要是一个实例Eq (Even though I did derive Eq in the data declaration) (即使我确实在数据声明中派生了Eq

The condition - Like I said, in the end you only really need to test that the particular elements are equal. 条件 -就像我说的,最后,您只需要真正测试特定元素是否相等即可。 It doesn't make sense to check if left1 == right2 && right1 == left2 since they shouldn't be equal , these branches should be mirrors of each other. 检查left1 == right2 && right1 == left2因为它们不应该相等 ,这些分支应该是彼此的镜像。

Guard instead of an if - I think guards are prettier than ifs. 后卫而不是if-我认为后卫比ifs更漂亮。

The pattern matches - It is a little cleaner (imho) to just have the catch-all False at the end. 模式匹配 -在末尾只包含全部False是一个更干净的(imho)。

I've been trying to learn QuickCheck lately so I also pumped out this code to prove that areMirrorImages works. 我最近一直在尝试学习QuickCheck,所以我也抽出了这段代码来证明areMirrorImages可以工作。

instance (Arbitrary a) => Arbitrary (BinaryTree a) where
    arbitrary = fromList `fmap` arbitrary

fromList :: [a] -> BinaryTree a
fromList []     = Empty
fromList (x:xs) = Node x (fromList lhalf) (fromList rhalf)
    where (lhalf, rhalf) = splitAt (length xs `div` 2) xs

mirror :: BinaryTree a -> BinaryTree a
mirror Empty = Empty
mirror (Node x l r) = Node x (mirror r) (mirror l)

prop_mirror tree = areMirrorImages tree (mirror tree)

My instance of Arbitrary for BinaryTree isn't the best; 我针对BinaryTreeArbitrary实例并不是最好的。 it only makes nearly-balanced trees. 它只会造出几乎平衡的树木。 But I figured it was pretty good. 但我认为这还不错。 Also note that prop_mirror only tests for when areMirrorImages should return True ; 另请注意, prop_mirror仅测试areMirrorImages应何时返回True it does not expose potential false positives (though I'm fairly sure there will be none). 它不会暴露潜在的误报(尽管我很确定不会有误报)。

*Main> quickCheck prop_mirror 
+++ OK, passed 100 tests.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM