我需要创建一个从preorder和inorder遍历构建树的函数,但是我不知道应该在哪里放置MakeNode和递归调用来正确构造树。
假设inorder和preorder都是一个int列表,下面的算法是否正确使用遍历来重建树?
def build(preorder, inorder):
root = preorder[0]
left subtree = inorder[:root-1]
right subtree = inorder[root+1:]
如果是这样 - 如何采用递归方式使用该算法来构建堆(ArrayHeap)? 我有一个用于构造节点的类,然后我可以简单地使用heap.add(node)来创建堆。
假设我的类构建一个节点名为“MakeNode”,并按如下方式构造(出于语法目的):
Class MakeNode():
def __init__(self, character, left=None, right=None):
要创建根节点,我需要编辑这样的函数:
def build(preorder, inorder, heap):
root = preorder[0]
node = MakeNode(root) # Creating root node here
heap.add(node) # Adding to heap
left subtree = inorder[:root-1]
right subtree = inorder[root+1:]
但是我应该如何使用递归来构建树的其余部分呢? 我可以通过这样做来合并左右预订单以进行订购:
def build(preorder, inorder, heap):
root = preorder[0]
node = MakeNode(root)
heap.add(node)
left subtree = inorder[:root-1]
# order of left subtree = preorder[1:1+left subtree]
right subtree = inorder[root+1:]
# order of right subtree = preorder[root+1:]
我真的不知道如何合并递归调用来构建树,或者在执行此操作时如何为左或右参数添加确切的内容。
如果有人有任何建议我会很感激,如果我不清楚,我很抱歉。
答案 0 :(得分:1)
您需要做的是将预先排序的列表的根添加到树中,然后将其从预订单列表中删除。按顺序拆分顺序列表,然后递归传递左右分支。继续在前一节点的左侧添加预订的第一个元素,除非left_subtree为空,然后您需要将其添加到右侧。
这样的事情(因为你要求伪代码而没有经过彻底的测试)
class tree():
def __init__(self, inorder, preorder):
self.root = preorder[0]
lt = inorder[:index(self.root) - 1]
rt = inorder[index(self.root) + 1:]
self.build(self.root, lt, rt, preorder[1:]
def build(self, last_node, left_subtree, right_subtree, preorder):
if len(left_subtree) > 0:
last_node.left = preorder[0]
last_node = last_node.left
lt = left_subtree[:index(preorder[0]) - 1]
rt = left_subtree[index(preorder[0]) + 1:]
self.build(last_node, lt, rt, preorder1:]
elif len(right_subtree) > 0:
last_node.right = preorder[0]
last_node = last_node.right
lt = right_subtree[:index(preorder[0]) - 1]
rt = right_subtree[index(preorder[0]) + 1:]
self.build(last_node, lt, rt, preorder1:]
答案 1 :(得分:1)
从http://www.cse.hut.fi/en/research/SVG/TRAKLA2/tutorials/heap_tutorial/taulukkona.html开始,您有:
parent(i) = i/2
left(i) = 2i
right(i) = 2i+1
所以你可以定义一个类:
class ArrayHeapNode:
def __init__(self, elements, index):
self.elements = elements
self.index = index
def left(self):
next = self.index * 2
if next >= len(self.elements):
return None
return ArrayHeapNode(self.elements, next)
def right(self):
next = (self.index * 2) + 1
if next >= len(self.elements):
return None
return ArrayHeapNode(self.elements, next)
def value(self):
return self.elements[self.index]
def set_value(self, _value):
self.elements[self.index] = _value
根据文章,这为您提供了一个类,该类可以作为二进制堆的数组表示形式的树。如果该分支中没有元素,则返回None
。
您现在可以创建树遍历算法(https://en.wikipedia.org/wiki/Tree_traversal):
def inorder_traversal(node, action):
if not node: return
inorder_traversal(node.left(), action)
action(node.value())
inorder_traversal(node.right(), action)
def preorder_traversal(node, action):
if not node: return
action(node.value())
preorder_traversal(node.left(), action)
preorder_traversal(node.right(), action)
这些也适用于传统的二叉树节点:
class BinaryTreeNode:
def __init__(self, value, left, right):
self._value = value
self._left = left
self._right = right
def left(self):
return self._left
def right(self):
return self._right
def value(self):
return self._value
def set_value(self, _value):
self._value = _value
现在,您可以通过执行以下操作使遍历算法更加灵活和类似python:
def inorder(node):
if node:
for item in inorder(node.left()):
yield item
yield node.value()
for item in inorder(node.right()):
yield item
这允许您编写如下内容:
for item in inorder(tree):
print item
然后,您可以通过执行以下操作来计算节点中的元素:
n = sum(1 for e in inorder(root))
然后,这允许您创建一个空数组,该数组能够为堆中的元素保存n个元素:
elements = [0 for x in range(n)]
或合并:
elements = [0 for x in inorder(root)]
heap = ArrayHeapNode(elements, 0)
现在,您可以使用以下方法同时迭代两棵树:
for a, b in zip(inorder(root), inorder(heap)):
b = a
然后,应该使用inorder遍历将二叉树中的所有元素(root
)分配给数组堆中的正确元素(heap
)。通过实现preorder
函数也可以做到这一点。
注意:我没有测试过这段代码。
答案 2 :(得分:0)
def pre_order(node):
print node #pre order ... print ourself first
pre_order(node.left)
pre_order(node.right)
def post_order(node):
post_order(node.left)
post_order(node.right)
print node # post order print self last...
def in_order(node):
in_order(node.left)
print node #in order ... between its children
in_order(node.right)
如果你有其中任何一个,你应该能够重现树
假设我们有这样的树
0
1 2
3 4 5 6
我们的遍历将是
0,1,3,4,2,5,6 #pre order
3,1,4,0,5,2,6 #in order
所以我们知道
0
...
3 6
我们的遗留节点是
1,4,2,5 # preorder
1,4,5,2 # in-order
由此我们知道
所以我们现在有了
0
1 2
3 6
离开我们
4,5 # pre order
4,5 # in order
由此我们知道4是1的孩子,因此5必须是2的孩子......
现在编写一个完成所有操作的函数
这篇文章可能有所帮助
http://leetcode.com/2011/04/construct-binary-tree-from-inorder-and-preorder-postorder-traversal.html