【问题标题】:Building a sum tree from leaves用树叶建造一棵总和树
【发布时间】:2017-10-27 23:29:50
【问题描述】:

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

输入:[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)

【问题讨论】:

  • 请问inplace 在这种情况下是什么意思?
  • 它不需要额外的内存。与我的每个递归级别创建一个新数组的解决方案不同。数组是要创建的 SumTree 底层的值。
  • 其次,你从哪里得到数组?它对元素的组织方式有一些逻辑结构吗?你能举个数组的例子吗?
  • 你打算展示预期的输入/输出吗?

标签: python algorithm recursion binary-tree


【解决方案1】:

通常是这样的:

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

【讨论】:

    【解决方案2】:

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

    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

    【讨论】:

      【解决方案3】:

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

      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)
      

      &lt;script src="//repl.it/embed/IUUa/2.js"&gt;&lt;/script&gt;

      【讨论】:

        猜你喜欢
        • 2018-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多