Construct completely balanced binary trees

In a completely balanced binary tree, the following property holds for every node: The number of nodes in its left subtree and the number of nodes in its right subtree are almost equal, which means their difference is not greater than one.

Write a predicate cbal_tree/2 to construct completely balanced binary trees for a given number of nodes. The predicate should generate all solutions via backtracking. Put the letter 'x' as information into all nodes of the tree. Example: ?- cbal_tree(4,T). T = t(x, t(x, nil, nil), t(x, nil, t(x, nil, nil))) ; T = t(x, t(x, nil, nil), t(x, t(x, nil, nil), nil)) ; etc......No

用单元测试描述为:

from python99.btree.p402 import cbal_tree def test_cbal_tree(): assert cbal_tree(4) == [ ['E', ['E', ['E', None, None], None], ['E', None, None]], ['E', ['E', None, ['E', None, None]], ['E', None, None]], ['E', ['E', None, None], ['E', ['E', None, None], None]], ['E', ['E', None, None], ['E', None, ['E', None, None]]] ]

这个题目可以用分治法解。整个问题是「构造包含N个节点的完全平衡二叉树」,可以被分解为三个小问题:

  1. 从N个节点中取一个节点作为根节点;
  2. 将剩余节点平分为二,相差不超过一,分别用于构造左右子树。

第2步又可以继续分解下去,直至最小问题「N为0」。

举个例子,给定N为4,则:

  • 取一个为根节点,剩余3。将3平分为2和1,枣差不超过1。分别用于构造左右子树。
    • 用2个节点构造左子树。先取一个作为子树的根节点,剩余1个节点。平分1为1和0,分别用于构造左右子树。
      • 用1构造左子树,取一个作为子树的根。剩余0,不分后为0和0。
        • 包含0个节点的右子树只能为空树
        • 包含0个节点的右子树只能为空树
      • 包含0个节点的右子树只能是空树
    • 用1个节点构造右子树﹐先取一个作为根。剩余0,平分为0和0
      • 包含0个节点的左子树只能是空树
      • 包含0个节点的右子树只能是空树

伐码实现:

import itertools def cbal_tree(n): if n == 0: return [None] element = 'E' num_of_right = (n-1)//2 num_of_left = (n - 1) - num_of_right a = [[element, left, right] for left in cbal_tree(num_of_left) for right in cbal_tree(num_of_right)] b = [[element, left, right] for left in cbal_tree(num_of_right) for right in cbal_tree(num_of_left)] result = a + b return [ii for n,ii in enumerate(result) if ii not in result[:n]]

results matching ""

    No results matching ""