Functional programming 标准ML:二叉树的大小计算不正确?
我的书具有以下函数,用于计算二叉树中非叶节点的数量:Functional programming 标准ML:二叉树的大小计算不正确?,functional-programming,sml,Functional Programming,Sml,我的书具有以下函数,用于计算二叉树中非叶节点的数量: fun size Empty = 0 | size(Node(t_1, _, t_2)) = size t_1 + size t_2 + 1; 假设我要计算二叉树中的所有节点。如何修改此函数以实现此目的 我是这么想的: fun size Empty = 0 | size(Node(Empty, _, Empty)) = 1 | size(Node(t_1, _, t_2)) = size t_1 + size t_
fun size Empty = 0
| size(Node(t_1, _, t_2)) = size t_1 + size t_2 + 1;
假设我要计算二叉树中的所有节点。如何修改此函数以实现此目的
我是这么想的:
fun size Empty = 0
| size(Node(Empty, _, Empty)) = 1
| size(Node(t_1, _, t_2)) = size t_1 + size t_2 + 1;
这个看起来对吗
谢谢
b外行Matt认为这两个函数在功能上是相同的,这两个函数都返回树中所有节点的计数。起初我没有注意到这一点,因为我从表面上看,您的第一个函数计算了非叶节点,然后注意到您的
节点(Empty,u,Empty)
模式是叶的正确模式(如果将叶定义为没有非空子节点的节点)。但是——这意味着书中的函数不仅仅计算非叶(父)节点。如果您确实想要一个只计算父节点的函数,那么您的模式毕竟是有用的:
fun parents Empty = 0
| parents(Node(Empty, _, Empty)) = 0
| parents(Node(t_1, _, t_2)) = parents t_1 + parents t_2 + 1;
如果树的应用程序大量使用父节点与叶节点的区别,则可以(以使某些函数定义更复杂为代价)放弃节点
构造函数,转而使用单独的父
和叶
构造函数。比如:
datatype 'a tree = Empty | Leaf of 'a | Parent of 'a tree * 'a * 'a tree;
然后您可以编写如下函数
fun countLeaves Empty = 0
| countLeaves (Leaf _) = 1
| countLeaves (Parent(t1,_,t2)) = countLeaves t1 + countLeaves t2;
例如
- val t = Parent(Parent(Leaf "2", "*", Leaf "3"), "+", Leaf "4");
- countLeaves t;
val it = 3 : int
您提供的两个实现实际上是相同的。第二种实现的第二种情况是第三种模式的特例。对于第一个实现,
size(Node(Empty,1,Empty))
将在左子树上递归一个,返回0,在右子树上递归一个,返回0,然后添加1,得到结果1。事实上,如果您切换第二种和第三种情况的顺序,编译器将告诉您它是冗余的:
test.sml:3.5-5.38 Error: match redundant
Empty => ...
Node (t_1,_,t_2) => ...
--> Node (Empty,_,Empty) => ...
但是改变顺序会改变功能,对吗?我的函数将返回3,如果你给…切换顺序会改变函数,因为它没有编译,因为冗余匹配错误。SMLNJ REPL给了我
1
对于我给出的示例,对于您的两个实现,大小(Node(Empty,1,Empty))
?再次感谢!将您的案例更改为空
案例以返回1,在我的示例中,这将为您提供3