标准ML:二进制树的大小计算错误?

时间:2015-08-12 19:58:33

标签: 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_2 + 1;

这看起来不错吗?

谢谢,

bclayman

2 个答案:

答案 0 :(得分:1)

Matt是正确的,你的两个函数在功能上是相同的 - 两者都返回树中所有节点的计数。起初我没有注意到这一点,因为我以第一个函数计算 nonleaf 节点的面值,然后注意到你的Node(Empty,_,Empty)模式是叶子的正确模式(如果叶子被定义为没有非空子节点的节点)。但是 - 这意味着书中的功能并不仅仅计算非叶(父)节点。如果你确实需要一个只计算父节点的函数,那么毕竟你的模式有用:

fun parents Empty = 0
    | parents(Node(Empty, _, Empty)) = 0
    | parents(Node(t_1, _, t_2)) = parents t_1 + parents t_2 + 1;

如果你的树的应用是一个大量使用父节点与叶节点区别的应用,你可以(以牺牲一些函数定义为代价)抛弃Node构造函数支持单独的ParentLeaf构造函数。类似的东西:

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

答案 1 :(得分:1)

您提供的两个实现实际上都是相同的。第二个实现的第二种情况是你的第三种模式的特殊情况。对于你的第一个实现,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) => ...