先序遍历和后序遍历为什么不能唯一地确定一棵树?:
https://blog.csdn.net/GYQJN/article/details/52709912
只有每个节点度为2或者0的时候前序和后序才能唯一确定一颗二叉树,只有一个子节点是无法确定的,因为你无法判断他是左子树还是右子树。
https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-postorder-traversal/
从来都是用来当填空题的。现在要求写程序。
比如:
cA B C F D E
a=['A','B','F','C','D','E'] #前序样子
b=['F','B','A','D','C','E'] #中序样子
c=['F','B','D','E','C','A'] #后序样子
规律:
要点:树的前序遍历第一个是根节点。长度关系。子数递归满足此条件。
pythonfrom typing import List
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def buildTreeFromPreorderInorder(self, preorder: List[str], inorder: List[str]) -> TreeNode:
n = len(preorder)
# 构造哈希映射,帮助我们快速定位根节点
index = {element: i for i, element in enumerate(inorder)}
def helper(preorder_left: int, preorder_right: int, inorder_left: int, inorder_right: int):
if preorder_left > preorder_right:
return None
# 前序遍历中的第一个节点就是根节点
preorder_root = preorder_left
# 在中序遍历中定位根节点
inorder_root = index[preorder[preorder_root]]
# 先把根节点建立出来
root = TreeNode(preorder[preorder_root])
# 得到左子树中的节点数目
size_left_subtree = inorder_root - inorder_left
# 递归地构造左子树,并连接到根节点
# 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
root.left = helper(preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1)
# 递归地构造右子树,并连接到根节点
# 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
root.right = helper(preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right)
return root
return helper(0, n - 1, 0, n - 1)
def buildTreeFromInorderPostorder(self, inorder , postorder):
temp=postorder[:]
def helper(in_left, in_right):
# 如果这里没有节点构造二叉树了,就结束
if in_left > in_right:
return None
# 选择 post_idx 位置的元素作为当前子树根节点
val = temp.pop()
root = TreeNode(val)
# 根据 root 所在位置分成左右两棵子树
index = idx_map[val]
# 构造右子树
root.right = helper(index + 1, in_right)
# 构造左子树
root.left = helper(in_left, index - 1)
return root
# 建立(元素,下标)键值对的哈希表
idx_map = {val: idx for idx, val in enumerate(inorder)}
return helper(0, len(inorder) - 1)
def constructFromPreorderPostorder(self, pre, post):
if not pre:
return None
node = TreeNode(pre[0])
if len(pre) == 1:
return node
i = post.index(pre[1])
node.left = self.constructFromPreorderPostorder(pre[1:i + 2], post[:i + 1])
node.right = self.constructFromPreorderPostorder(pre[i + 2:], post[i + 1:-1])
return node
def preorderTraversal(self, root: TreeNode) -> List[str]:
def preorder(root: TreeNode):
if not root:
return
res.append(root.val)
preorder(root.left)
preorder(root.right)
res = list()
preorder(root)
return res
def inorderTraversal(self, root: TreeNode) -> List[str]:
def preorder(root: TreeNode):
if not root:
return
preorder(root.left)
res.append(root.val)
preorder(root.right)
res = list()
preorder(root)
return res
def postorderTraversal(self, root: TreeNode) -> List[int]:
def postorder(root: TreeNode):
if not root:
return
postorder(root.left)
postorder(root.right)
res.append(root.val)
res = list()
postorder(root)
return res
a = ['A', 'B', 'F', 'C', 'D', 'E'] #前序样子
b = ['F', 'B', 'A', 'D', 'C', 'E'] #中序样子
c = ['F', 'B', 'D', 'E', 'C', 'A'] #后序样子
onexianxu=Solution().buildTreeFromInorderPostorder(b,c)
print('先序',Solution().preorderTraversal(onexianxu))
onezhong=Solution().constructFromPreorderPostorder(a, c)
print('中序',Solution().inorderTraversal(onezhong))
onehouxu=Solution().buildTreeFromPreorderInorder(a,b)
print('后序',Solution().postorderTraversal(onehouxu))
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!