考虑n个节点的二叉树。为了举例,请考虑以下树:
1
/ \
2 3
/ \ / \
4 5 6 7
\
8
有多少种不同的方法可以从根(顶部)节点开始完全遍历树,只移动到与已访问过的节点直接相连的未访问节点(即我可以从1到2到4然后到3)?
答案 0 :(得分:5)
你可能会有更多运气询问数学堆栈交换。
您要求将二进制树的线性扩展数视为一个poset。虽然我看不到通用公式,但可以递归地解决这个问题,如下所示:
找到遍历左右子树的方法的数量(以一种方式简单地遍历空树)。调用这些T_L和T_R。设#L和#R分别是左树和右树的基数(大小)。然后遍历整个树的方式是
T_L * T_R *(#L + #R选择#L)
因为我们可以用T_L方式遍历左侧树,以T_R方式遍历右侧树(独立于我们如何遍历右侧树),并且我们可以交错左右树(#L + #R选择#L)方式。
在你的例子中,有两种遍历左树的方法,三种遍历右树的方法和(7选择3)是35,所以有2 * 3 * 35 = 210种遍历树的方法。 / p>
答案 1 :(得分:1)
使用Prolog编译验证@deinst的答案:
traverse([], []) :- !.
traverse(F, [N|P]) :-
% select a frontier node from F
select(t(N,C), F, Rem),
% append all new accessible children to the frontier
append(C, Rem, NewF),
% traverse the remaining set
traverse(NewF, P).
tree(X) :-
X = t(1,[t(2,[t(4,[]), t(5,[])]),t(3,[t(6,[]), t(7,[t(8,[])])])]).
do :-
tree(X),
findall(P, (traverse([X], P), write_ln(P)), Ps),
length(Ps, L),
write_ln(L).
这确实会返回210种可能性,正如您的示例树所建议的那样。
?- do.
[1,2,4,5,3,6,7,8]
[1,2,4,5,3,7,8,6]
[1,2,4,5,3,7,6,8]
[1,2,4,3,6,7,8,5]
[1,2,4,3,6,7,5,8]
[1,2,4,3,6,5,7,8]
[1,2,4,3,7,8,6,5]
[1,2,4,3,7,8,5,6]
[1,2,4,3,7,6,8,5]
...
[1,3,2,7,6,4,8,5]
[1,3,2,7,6,4,5,8]
[1,3,2,7,6,5,8,4]
[1,3,2,7,6,5,4,8]
210
true.