Haskell 查看BST的大小

Haskell 查看BST的大小,haskell,Haskell,假设我有data BSearch x y=None | Node x y(BSearch x y)(BSearch x y)(这意味着树要么是空的,要么不是空的),我正在尝试编写函数,bstSize::BSearch x y->Int 它基本上是这样运行的 > bstSize None 0 > bstSize (Node 0 57 Empty (Node 0 65 Empty Empty)) 2 我知道如何定义一个有1个节点的树和一个有2个节点的树,但是我很难理解如何将该模式实

假设我有
data BSearch x y=None | Node x y(BSearch x y)(BSearch x y)
(这意味着树要么是空的,要么不是空的),我正在尝试编写函数,
bstSize::BSearch x y->Int

它基本上是这样运行的

> bstSize None
0
> bstSize (Node 0 57 Empty (Node 0 65 Empty Empty))
2  
我知道如何定义一个有1个节点的树和一个有2个节点的树,但是我很难理解如何将该模式实现为第n个节点的实际代码。我唯一能想到的就是计算右括号的数量,计算参数中出现“节点”的次数,或者计算参数中出现“空”的次数减去1,我真的不知道如何做这些事情。我知道我可能必须使用递归,但我不确定我将如何使用它。以下是我到目前为止的情况:

data BSearch q w = None | Node q w (BSearch q w) (BSearch q w)
bstSize :: BSearch q w -> Int
bstSize Empty = 0
bstSize(Node a b None None) = 1
bstSize(Node a b None (Node a b None None))) = 2
bstSize(Node a b None (Node a b None (Node a b None None))))) = 3

显然,我不应该直接定义2、3、4等的样子,但我这样做是为了看看这个模式是什么样子,看看我能用什么。到目前为止,我真的不知道该怎么做。

您需要使用递归:

Data BSearch q w = None | Node q w (BSearch q w) (BSearch q w)
bstSize :: BSearch q w -> Int
bstSize None = 0
bstSize(Node _ _ la lb) = 1 + bstSize la + bstSize lb
您在将
Empty
更改为
None
时犯了一个小错误

此外,
节点的大小
是1加上左子节点和右子节点的大小。您可以使用递归来实现这一点。使用递归,可以对不同的输入调用相同的方法(在本例中是节点的子级)

因为每棵树都是空的。最终所有的孩子都会死

这是如何工作的?

假设您有值
节点a b None(节点a b None(节点a b None))
,然后函数调用

bstSize (Node a b None (Node a b None (Node a b None None))))) --1st call
la
None
lb
统一(节点a b None(节点a b None-None))
。现在,该函数调用
bstSize la
bstSize lb
。由于
la
None
,因此第一次调用将返回
0
。对于第二次呼叫,它更复杂

第二个电话是:

bstSize Node a b None (Node a b None None))))  --2nd call
现在在这个函数调用中,
la
None
统一,因此结果为零,
lb
节点a b None
统一。这将导致第三次呼叫:

bstSize (Node a b None None) --3rd call
由于
la
lb
都统一为
None
,它们的结果都是
0
,因此结果是:

bstSize (Node a b None None) --3rd call
= 1 + bstSize None + bstSize None
= 1+0+0
= 1
bstSize (Node a b None (Node a b None (Node a b None None))) --1st call
= 1 + bstSize None + bstSize (Node a b None (Node a b None None))
= 1 + 0 + 2
= 3
结果返回到第二个调用:

bstSize Node a b None (Node a b None None)))) --2nd call
= 1 + bstSize None + bstSize (Node a b None None)))) 
= 1 + 0 + 1
= 2
最终结果是:

bstSize (Node a b None None) --3rd call
= 1 + bstSize None + bstSize None
= 1+0+0
= 1
bstSize (Node a b None (Node a b None (Node a b None None))) --1st call
= 1 + bstSize None + bstSize (Node a b None (Node a b None None))
= 1 + 0 + 2
= 3

递归是一个强大的概念,但很容易导致无限循环。您最好确保始终使用不同于给定元素的递归调用,并且调用树是有限的。

以下是在最近的GHC中作弊的方法。不要在课堂作业中尝试这个

{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}

module MyModuleNotYours
import qualified Data.Foldable as F

data BSearch x y = None
                 | Node x y (BSearch x y) (BSearch x y)
  deriving (F.Foldable, Functor)

bstSize :: BSearch x y -> Int
bstSize = F.sum . (1 <$)
{-#语言派生可折叠}
{-#语言派生函子#-}
模块MyModuleNotYours
导入符合条件的数据。可折叠为F
数据b搜索x y=无
|节点x y(b搜索x y)(b搜索x y)
派生(F.可折叠,函子)
bstSize::BSearch x y->Int

bstSize=F.sum。(1看起来您需要一些递归…提示:您不需要指定树的整个骨架;当前节点的子节点也可以由变量绑定。如:
bstSize(node a b l r)=……