Count the nodes of a multiway tree
题目
Write a predicate nnodes/1 which counts the nodes of a given multiway tree. Example: ?- nnodes(t(a,[t(f,[])]),N). N = 2
Write another version of the predicate that allows for a flow pattern (o,i).
用单元测试描述为:
from python99.mtree.p502 import nnodes
def test_nnodes():
assert nnodes(('a', [('b', [('c', []), ('d', [])])])) == 4
解题思路
多路树是一个递归定义的结构,所以用递归算法来统计节点数是最自然的了。
- 首先统计根节点
- 分别统计每棵子树的节点数(子树都是多路树,所以这𥚃直接套用步骤1至3)
- 合计所有子树的节点数加根节点
举个例子,有多路树(a,[(b,[(c,[]),(d,[])])])
。
- 先统计根节点为1
- 再统计每一棵子树,这𥚃有一棵子树
(b,[(c,[]),(d,[])])
- 先统计根节点数为1
- 再统计每一棵子树,这𥚃有两棵子树
(c,[]),(d,[])
- 针对
(c,[])
,先统计根节点为1,其没有子树。所以整棵子树的节点数为1 - 针对
(d,[])
,先统计根节点为1,其没有子树。所以整棵子树的节点数为1
- 针对
- 合计所有子树的节点数和自身根节点数,
1+1=1=3
。本子树的节点縂数为3
- 合计所有子树的节点数再加上自身根节点数,
3+1=4
。縂计4个节点
代码实现:
from functools import reduce
from operator import add
def nnodes(t):
return reduce(add, [nnodes(e) for e in t[1]], 1)
reduce
是Python标准库提供的一个函数式的工具,其声明为:
reduce(function, iterable, initializer)
其功能是将function
累积地、从左往右作用于iterable
中的每一个元素。
reduce相当于如下代码:
def reduce(function, iterable, initializer=None):
it = iter(iterable)
if initializer is None:
value = next(it)
else:
value = initializer
for element in it:
value = function(value, element)
return value
这𥚃我们使用reduce实现累加的功能。其将所有子树节点数累加起来,本身节点数1以initializer
的形式被累加进来。