遍历二叉树的方法数量

时间:2015-10-12 01:02:25

标签: algorithm tree binary-tree binary-search-tree

考虑n个节点的二叉树。为了举例,请考虑以下树:

     1
   /   \
  2     3
 / \   / \
4   5 6   7
           \
            8

有多少种不同的方法可以从根(顶部)节点开始完全遍历树,只移动到与已访问过的节点直接相连的未访问节点(即我可以从1到2到4然后到3)?

2 个答案:

答案 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.