问题描述
class Node:
def __init__(self,data,left=None,right=None):
self.data = data
self.left = left
self.right = right
def construct(start,end,preorder,pIndex,dict):
# base case
if start > end:
return None,pIndex
root = Node(preorder[pIndex])
pIndex = pIndex + 1
index = dict[root.data]
root.left,pIndex = construct(start,index - 1,dict)
root.right,pIndex = construct(index + 1,dict)
return root,pIndex
def constructTree(inorder,preorder):
dict = {}
for i,e in enumerate(inorder):
dict[e] = i
pIndex = 0
return construct(0,len(inorder) - 1,dict)[0]
if __name__ == '__main__':
inorder = [4,2,1,7,5,8,3,6]
preorder = [1,4,6]
root = constructTree(inorder,preorder)
print("The inorder traversal is ",end='')
inorderTraversal(root)
preorderTraversal(root)
这段代码构造了一个带有前序和中序遍历的树。如何修改该代码以使其适用于 inorder-postorder 和 preorder-postorder?我想我只需要以类似的方式修改 construct()
并创建 constructPreOrderInorderTree()
和 constructPreOrderpostorderTree()
。
编辑
假设我有 inorder=[3,10,9,6,2]
和 postorder = [3,5]
。 construct()
会为 inorder-preorder 这样做,但它不适用于该示例。所以我需要一个可以同时使用 inorder-postorder 和 preorder-postorder 的函数版本。
解决方法
变化:
- 使用像
lookup
这样的变量名以避免掩盖现有的类型名称(例如dict
) - 从右到左
- 从头开始
- 一路递减 pIndex
- 从相反方向更新 pIndex
def construct_post(start,end,postorder,pIndex,lookup):
# base case
if start > end or pIndex < 0:
return None,pIndex
root = Node(postorder[pIndex])
# go from the right to the left instead
pIndex = pIndex - 1
index = lookup[root.data]
# update pIndex going in the opposite direction
root.right,pIndex = construct_post(index + 1,lookup)
root.left,pIndex = construct_post(start,index - 1,lookup)
return root,pIndex
def constructTree_post(inorder,postorder):
lookup = {e: i for i,e in enumerate(inorder)}
pIndex = len(postorder) - 1
# start from the end
return construct_post(0,len(inorder) - 1,lookup)[0]
结果树:
1
/ \
2 3
/ / \
4 5 6
/ \
7 8
,
我什至没有阅读 Geeks-for-Geeks 页面,就决定实现我自己的构造函数算法(前序-后序、前序-中序、中序-后序)。
我所有的算法都是 O(N^2)
复杂度。
除了构造函数(construct_preorder_postorder()
、construct_preorder_inorder()
、construct_inorder_postorder()
)我还实现了遍历函数(traverse_preorder()
、traverse_inorder()
、traverse_postorder()
),控制台树打印函数(print_tree()
)和节点相等比较函数(__eq__()
)。
class Node:
def __init__(self,data,left = None,right = None):
self.data = data
self.left = left
self.right = right
def __eq__(self,other):
return (self.data == other.data and self.left == other.left and
self.right == other.right)
def traverse_inorder(node):
return ([] if node is None else
traverse_inorder(node.left) + [node.data] + traverse_inorder(node.right))
def traverse_preorder(node):
return ([] if node is None else
[node.data] + traverse_preorder(node.left) + traverse_preorder(node.right))
def traverse_postorder(node):
return ([] if node is None else
traverse_postorder(node.left) + traverse_postorder(node.right) + [node.data])
def construct_preorder_postorder(pre,post):
assert sorted(pre) == sorted(post) and len(pre) == len(set(pre)),(pre,post)
if len(pre) == 0:
return None
if len(pre) == 1:
return Node(pre[0])
root,l = pre[0],pre[1]
for i,e in enumerate(post):
if e == l:
ls = i + 1
rs = len(post) - 1 - ls
break
return Node(root,None if ls == 0 else construct_preorder_postorder(pre[1:1 + ls],post[:ls]),None if rs == 0 else construct_preorder_postorder(pre[-rs:],post[-1 - rs:-1]))
def construct_preorder_inorder(pre,ino):
assert sorted(pre) == sorted(ino) and len(pre) == len(set(pre)),ino)
if len(pre) == 0:
return None
if len(pre) == 1:
return Node(pre[0])
root,e in enumerate(ino):
if e == root:
ls = i
rs = len(ino) - 1 - ls
break
return Node(root,None if ls == 0 else construct_preorder_inorder(pre[1:1 + ls],ino[:ls]),None if rs == 0 else construct_preorder_inorder(pre[-rs:],ino[-rs:]))
def construct_inorder_postorder(ino,post):
assert sorted(ino) == sorted(post) and len(ino) == len(set(ino)),(ino,post)
if len(post) == 0:
return None
if len(post) == 1:
return Node(post[0])
root,r = post[-1],post[-2]
for i,None if ls == 0 else construct_inorder_postorder(ino[:ls],None if rs == 0 else construct_inorder_postorder(ino[-rs:],post[-1 - rs:-1]))
def print_tree(node):
def inner(node,*,upref = '',cpref = '',dpref = ''):
if node is None:
return
inner(node.right,upref = dpref + ' |',cpref = dpref + ' /',dpref = dpref + ' ')
print(cpref + '--' + str(node.data))
inner(node.left,upref = upref + ' ',cpref = upref + ' \\',dpref = upref + ' |')
inner(node)
if __name__ == '__main__':
node = Node(1,Node(2,Node(4)),Node(3,Node(5,Node(7),Node(8)),Node(6)))
print_tree(node)
preorder,inorder,postorder = (
traverse_preorder(node),traverse_inorder(node),traverse_postorder(node))
preorder_cons,inorder_cons,postorder_cons = (
construct_preorder_postorder(preorder,postorder),construct_preorder_inorder(preorder,inorder),construct_inorder_postorder(inorder,)
assert preorder_cons == inorder_cons == postorder_cons
输出:
/--6
/--3
| | /--8
| \--5
| \--7
--1
\--2
\--4