【问题标题】:Checking if two n-ary trees are equal in Haskell在 Haskell 中检查两个 n-ary 树是否相等
【发布时间】:2012-12-13 18:41:28
【问题描述】:

我正在尝试在 Haskell 中实现一个简单的布尔函数来检查两个 n 元树是否相等。

我的代码是:

-- This is the n-ary tree definition.
-- (I know "Leaf a" is not necessary but I prefer to write it for clarity)
data Tree a = Leaf a | Node a [Tree a]
    deriving (Show)

-- This is a simple tree used for test purposes
t :: Tree Int
t = Node 3 [Node 5 [Leaf 11, Leaf 13, Leaf 15], Leaf 7, Leaf 9]

treeEquals :: Eq a => Tree a -> Tree a -> Bool
treeEquals (Leaf n1) (Leaf n2) = n1 == n2
treeEquals (Node n1 xs1) (Node n2 xs2) = n1 == n2 && and(zipWith (treeEquals) xs1 xs2)
treeEquals _ _ = False

我的问题是,如果我进行以下测试:

treeEquals t t
treeEquals t (Leaf 3)
treeEquals t (Node 3 [Leaf 7])

它正确返回 false,因为树不相等,但如果我尝试如下测试:

treeEquals t (Node 3 [])

它不起作用,因为它在树相等时返回 true。

你知道我做错了什么吗?

【问题讨论】:

  • 有没有更好的方法来实现这个方法而不使用 zipWith 避免两个列表遍历?
  • 以这种方式使用Leaf实际上会导致冗余表示:Node x [] vs Leaf x。冗余表示通常应仅出于充分的理由使用(例如,如果它们允许某些操作更快)。在这种情况下,仅仅删除Leaf 构造函数似乎是最好的做法。或者,您可以将 Node 构造函数更改为 Node a (Tree a) [Tree a],但何必呢?

标签: haskell tree equals


【解决方案1】:

为什么不直接派生Eq 并使用==?

您当前代码的问题是zipWith。它在到达较短列表的末尾时立即停止,因此zipWith treeEquals foo [] 总是返回[](不管foo 是什么)。

这是一个(未经测试的)替代解决方案:

treeEquals :: Eq a => Tree a -> Tree a -> Bool
treeEquals (Leaf n1) (Leaf n2) = n1 == n2
treeEquals (Node n1 xs1) (Node n2 xs2) = n1 == n2 && listTreeEquals xs1 xs2
    where
    listTreeEquals [] [] = True
    listTreeEquals (x1 : xs1) (x2 : xs2) = treeEquals x1 x2 && listTreeEquals xs1 xs2
    listTreeEquals _ _ = False
treeEquals _ _ = False

【讨论】:

  • 感谢您的回答。是的,我明白了问题所在。不幸的是,我必须实施自己的方法,因为我必须为考试锻炼自己。我正在尝试实现他们可能问我的所有可能的事情,所以我不能只使用 ==。
  • @JohnQ (==) 这里很酷的一点是,即使你不推导出它,而是自己实现它,你也可以定义(Node n1 xs1) == (Node n2 xs2) = n1 == n2 && xs1 == xs2 [加上其他情况的方程,@ 987654330@ 和 _/_]。然后xs1 == xs2 使用通用instance Eq a => Eq [a] 来做正确的事情。对于您的treeEquals,您可以简单地使用treeEquals = (==) ;)
【解决方案2】:

在 zipWith 之前添加另一个 && 并检查列表的长度是否相同。

【讨论】:

  • 这样做意味着潜在的两个列表遍历 - 首先最好不要使用 zipWith。
  • @Darwin,感谢您的回答。没想到,这么简单!
猜你喜欢
  • 1970-01-01
  • 2014-04-18
  • 2012-01-10
  • 2016-09-18
  • 2015-08-21
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 2011-08-09
相关资源
最近更新 更多