从树叶建立一个总和树

时间:2017-05-27 02:11:21

标签: python algorithm recursion binary-tree

嘿,我正在准备考试,我可以使用一些帮助。 任务是从叶子的值数组(从左到右)构建二进制和树(父节点键是子键的总和),其总是2 ^ n长。我首先将数组转换为节点数组。然后我做了一个递归函数,它结合了对,并在一个新创建的节点数组上调用它自己。有没有更好的方法来完成这项任务?也许就是"到位"? e.g。

输入:[1,2,3,4]

输出:

      10
    /    \
   3      7
  / \    / \
 1   2  3   4
class SumTree:
    def __init__(self):
        self.root = None

class Node:
    def __init__(self):
        self.key = 0
        self.parent = None
        self.left = None
        self.right = None

def makeNode(key):
    n = Node()
    n.key = key
    return n

def buildSumTree(array):
    for i in range(len(array)):
        array[i] = makeNode(array[i])
    tree = SumTree()
    tree.root = buildSumTree_rec(array)
    return tree

def buildSumTree_rec(array):
    if len(array) == 1 :
        return array[0]
    else:       
        a = []
        for i in range(0, len(array) // 2, 2):
            n = makeNode(array[i].key + array[i + 1].key)
            n.left = array[i]
            n.right = array[i + 1]
            array[i].parent = n
            array[i + 1].parent = n
            a.append(n)
        return buildSumTree_rec(a)

3 个答案:

答案 0 :(得分:0)

通常是这样的:

def buildSumTree(array):
    return buildSumTree2(array, 0, len(array))

def buildSumTree2(array, startpos, length):
    if length < 1:
        return None
    if length == 1:
        return makeNode(array[startpos])
    halflen = length/2
    l = buildSumTree2(array, startpos, halflen)
    r = buildSumTree2(array, startpos+halflen, length-halflen)
    n = makeNode(l.key + r.key)
    n.left = l
    n.right = r
    return n

答案 1 :(得分:0)

以下代码构建从树叶到根的树。它重复将两个子节点连接到新创建的父节点,直到只剩下一个节点。

class Node:
    def __init__(self, left, right):
        self.left = left
        self.right = right
        self.value = sum(n.value for n in (left, right) if n is not None)

    @classmethod
    def create_leaf(cls, value):
        leaf = cls(None, None)
        leaf.value = value
        return leaf


INPUT = [1, 2, 3, 4]

nodes = [Node.create_leaf(v) for v in INPUT]
while len(nodes) > 1:
    inodes = iter(nodes)
    nodes = [Node(*pair) for pair in zip(inodes, inodes)]

root_node = nodes[0]

成对迭代基于:Iterating over every two elements in a list

答案 2 :(得分:0)

此实现仅存储叶子而不存储任何其他内容,因此不使用额外的内存来存储节点。它也不会改变叶子,即不进行任何改变,只进行读取操作。所有其他信息都是即时计算的。目前输出是基本的,每深度一行。

import math

class SumTree:

  def __init__(self, leaves):
    self.leaves = leaves

  def nodeAt(self, i, j):
    if i < self.height() - 1:
      return self.nodeAt(i+1, 2*j) + self.nodeAt(i+1, 2*j+1)
    elif i == self.height() - 1:
      return self.leaves[j]
    else:
      raise 'no nodes exists at this depth.'

  def nodesAtDepth(self, i):
    return [self.nodeAt(i, j) for j in range(self.widthAtDepth(i))]

  def maxWidth(self):
    return self.widthAtDepth(self.height() - 1)

  def widthAtDepth(self, i):
    return 2 ** i

  def height(self):
    return math.floor(math.log(len(self.leaves), 2)) + 1

  def __str__(self):
    result = ''
    width = self.maxWidth()
    for i in range(self.height()):
      result += '{}\n'.format(self.nodesAtDepth(i))
    return result

tree = SumTree(list(range(1, 5)))
print('leaves', tree.leaves)
print('height', tree.height())
print(tree)

<script src="//repl.it/embed/IUUa/2.js"></script>