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