Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 查找树中节点的最大值_Haskell_Binary Tree - Fatal编程技术网

Haskell 查找树中节点的最大值

Haskell 查找树中节点的最大值,haskell,binary-tree,Haskell,Binary Tree,我有个问题 我必须在Haskell中实现一个函数maxT,它从二叉树返回节点的最大值 data Tree a = Leaf a | Node (Tree a) a (Tree a) 这是给定的。接下来我该怎么办 maxT :: (Tree Integer) -> Integer maxT (Leaf a) = a maxT (Node l a r) = max a (max (maxT l) (maxT r)) 这是对的吗?让我们看看要证明这是正确的有多难。为什么?因为这是分析程序错误

我有个问题

我必须在Haskell中实现一个函数
maxT
,它从二叉树返回节点的最大值

data Tree a = Leaf a | Node (Tree a) a (Tree a)
这是给定的。接下来我该怎么办

maxT :: (Tree Integer) -> Integer
maxT (Leaf a) = a
maxT (Node l a r) = max a (max (maxT l) (maxT r))

这是对的吗?

让我们看看要证明这是正确的有多难。为什么?因为这是分析程序错误的好方法。尤其是递归的。从技术上讲,我们将使用归纳法,但它并不复杂。关键是要认识到
maxtt
必须始终是树中的最大值
t
——这个声明,“
maxtt
必须始终是树中的最大值
t
”被称为不变量,我们将尝试证明它

首先,我们假设
t
是一个
Leaf
。在这种情况下,您已经定义了
maxT(Leaf a)=a
,并且由于此树中没有其他值,
a
必须是最大的。因此,
maxT
在传递
Leaf
时支持我们的不变量。这就是“基本情况”


<>现在我们将考虑当我们让<代码> T =节点(叶A)B(叶C)某些<代码>整数< /代码> S代码> A <代码> >代码> B>代码>和<代码> C/<代码>。这是一个高度为1的树,形成了一个你可以称之为归纳的“示例案例”。让我们试试
maxT
,看看不变量是否成立

maxT t 
===
maxT (Node (Leaf a) b (Leaf c))
===
max b (max (maxT (Leaf a)) (maxT (Leaf c)))
此时,我们将使用我们的基本情况步骤,并说,由于此表达式中的
maxT
的唯一应用程序位于
Leaf
s上,因此每个应用程序都必须支持我们的不变量。这有点愚蠢,但那只是一个例子。稍后我们将看到更一般的模式

现在,让我们计算
maxT(Leaf)
位,知道结果是每个特定的左或右子树中的最大值

===
max b (max a c)
现在,我不太想深入讨论
max
的定义,但基于它的名称,我很高兴假设
max a b
返回的值在
a
b
之间最大。我们可以在这里选择详细信息,但很明显,
max b(max a c)
已经获得了有关
节点的所有相关信息,用于计算整个height-1树的最大值。我认为这是一个成功的证明,
maxT
对height-0和height-1树都有效(
Leaf
s和
Node
s只包含
Leaf
s)

下一步是概括这个例子


让我们在树的高度上应用同样的模式。我们将询问如果我们固定一些数字,
n
,并假设
maxtt
对高度
n
或更低的所有
t
保持不变,会发生什么。这有点奇怪,我们只展示了这对
n=0
n=1
有效。稍后会很清楚为什么会这样

那么这个假设对我们有什么作用呢?好的,让我们取任意两棵高度小于等于n的树(称它们为l和r),任意整数x,并将它们组合成一棵新树。当我们执行
maxtt
时会发生什么

maxT t
===
maxT (Node x l r)
===
max x (max (maxT l) (maxT r))
我们知道,根据我们的假设,
maxtl
maxtr
支持我们的不变量。然后,
max
es链继续支持我们现在对树
t
的不变量,即高度-
(n+1)
。此外(这非常重要)我们组装新的
树的过程是通用的,我们可以用这种方法制作任意高度的
(n+1)
树。这意味着
maxT
适用于任何高度-
(n+1)


诱导时间!我们现在知道,如果我们选择一个
n
,并且(出于某种原因)相信
maxT
适用于任何高度-
n
树,那么它必须立即适用于任何高度-
(n+1)
树。让我们选择
n=0
。通过“基本情况”我们知道
maxT
适用于
Leaf
s,因此我们突然知道
maxT
适用于高度-
1
树。这就是我们的“案例”。现在,根据这些知识,我们可以立即看到
maxT
适用于高度-
2
树。然后是高度-
3棵树。然后是高度-
4
。等等等等

这就完成了
maxT
正确性的证明*


*我必须留下一些警告。我们并没有真正做精细的细节来说明
max
链是可行的,尽管这是有道理的。我也没有真正证明归纳步骤是有效的,如果有更多的方法来创建一个高度-
(n+1)
树,而不仅仅是在高度-
n
或更小的树上使用
节点,会怎么样?更有效的方法是“拆开”一棵高的树,但我认为这更难看到。最后,我们想认真考虑一下,如果我们发送
maxT(Leaf undefined)
或其他类似的病理值,会发生什么。这些出现在Haskell中,因为它是一种(图灵完整的)计算机语言,而不是纯数学。老实说,对于您的情况来说,这些小细节不会有太大的改变。

这不是最完美的实现,但在我看来,它应该可以工作。你能详细说明一下你认为它有什么问题吗?你可能想把它的类型概括为
maxT::Ord a=>Tree a->a
,但除此之外,它看起来还不错。你试过测试它吗?试试这个:
maxT(节点(叶1)5(叶(-4)))2(节点(叶6)2(叶4))
。你没有问题!