数据结构------二叉树
本文使用python语言实现
目录图示:
本文所用二叉树图示:
来先做一下这道题:
先序遍历为: ABDEFGCHK
中序遍历为: DBFEGACKH
后序遍历为: DFGEBKHCA
层次遍历为: ABCDEHFGK
0> 树节点的定义:
class TreeNode:
def __init__(self, x=None,left=None,right=None):
self.val = x
self.left = left
self.right = right
1> 先序遍历:
def preorderTraversal(root): #先序 迭代
if root is None:
return []
stack, output = [root, ], []
while stack:
root = stack.pop()
output.append(root.val)
if root.right is not None:
stack.append(root.right)
if root.left is not None:
stack.append(root.left)
return output
def preorderTraversal1(root): #先序 递归
output = []
def helper(root):
if not root: return
output.append(root.val)
helper(root.left)
helper(root.right)
helper(root)
return output
2> 中序遍历:
def inorderTraversal(root): #中序迭代
if root is None:
return []
stack, output = [], []
while stack or root: # 栈为空并且目前的节点为空则结束
while root: # 遍历左节点,一路到底
stack.append(root)
root = root.left
if stack: # 取出到头的那个左孩子,再返回while找右孩子的左孩子一路到底,要是没有右则继续出栈
a = stack.pop()
output.append(a.val)
root = a.right
return output
def inorderTraversal1(root): #中序递归
output = []
def helper(root):
if not root:
return
helper(root.left)
output.append(root.val)
helper(root.right)
helper(root)
return output
3> 后序遍历:
def postorderTraversal(root):#后序迭代
if root is None: # 可以看作前序遍历(先左子树后右子树) 先遍历右子树再左子树(先左入栈), 输出倒序
return []
stack, output = [root, ], []
while stack:
root = stack.pop()
output.append(root.val)
if root.left is not None:
stack.append(root.left)
if root.right is not None:
stack.append(root.right)
return output[::-1]
def postorderTraversal1(root):#后序递归
output = []
def helper(root):
if not root:
return
helper(root.left)
helper(root.right)
output.append(root.val)
helper(root)
return output
4> 层次遍历:
def levelOrder(root): #层次递归
if root is None:
return []
levels = []
def inlevels(node, level):
if len(levels) == level: #树是0级一级二级 对应levels的长度为1 2 3 当长度和目前的级数相等时,说明树的这一级还没地方放 要append
levels.append([])
levels[level].append(node.val)
if node.left is not None:
inlevels(node.left,level+1)
if node.right is not None:
inlevels(node.right,level+1)
inlevels(root, 0)
return levels
def levelOrder1(root): #层次迭代
levels = []
if not root:
return levels
level = 0
queue = deque([root, ])
while queue:
levels.append([])
level_length = len(queue) #这一级的节点数
for i in range(level_length):
node = queue.popleft()
levels[level].append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
level += 1
return levels
测试如下:
if __name__=='__main__':
root = TreeNode('A', TreeNode('B', TreeNode('D'),TreeNode('E', TreeNode('F'), TreeNode('G'))),TreeNode('C', right=TreeNode('H', left=TreeNode('K'))))
a = preorderTraversal(root);print('先序遍历迭代:', a)
a = preorderTraversal1(root);print('先序遍历递归:', a)
a = inorderTraversal(root);print('中序遍历迭代:', a)
a = inorderTraversal1(root);print('中序遍历递归:', a)
a = postorderTraversal(root);print('后序遍历迭代:', a)
a = postorderTraversal1(root);print('后序遍历递归:', a)
a = levelOrder(root);print('层次遍历递归:', a)
a = levelOrder(root);print('层次遍历迭代:', a)
运行结果如下:
5>构造二叉树
构造二叉树即已知先序遍历中序遍历后序遍历的其中两个,依此来构造二叉树。
1.已知一棵树的中序遍历inorder和后序遍历postorder(均为列表形式):
中序遍历为左中右,后序遍历为左右中,即根节点root的值为postorder[-1],设为val,然后找到val在inorder中的索引i,左边为左子树,右边为右子树
inorder 为:[左子树的中序遍历 val 右子树的中序遍历] postorder 为:[左子树的后序遍历 右子树的后序遍历 val]
然后 迭代
root.left的新inorder为inorder[:i],新postorder为postorder[:i]
root.right的新inorder为inorder[i+1:],新postorder为postorder[i:-1]
代码如下:
def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
if not inorder or not postorder:
return None
val = postorder[-1]
root = TreeNode(val)
i = inorder.index(val)
root.left = self.buildTree(inorder[:i],postorder[:i])
root.right = self.buildTree(inorder[i+1:],postorder[i:-1])
return root
2.已知一棵树的先序遍历preorder和中序遍历inorder:
和上一个类似
preorder 为:[val 左子树的中序遍历 右子树的中序遍历] inorder 为:[左子树的后序遍历 val 右子树的后序遍历]
代码如下:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if not preorder or not inorder:
return None
val = preorder[0]
root = TreeNode(val)
i = inorder.index(val)
root.left = self.buildTree(preorder[1:i+1],inorder[:i])
root.right = self.buildTree(preorder[i+1:len(preorder)],inorder[i+1:])
return root
3.已知一棵树的先序遍历preorder和后序遍历postorder:
这种情况得出的结果可能不止一个!(除非每个根节点都有两个子节点)
举例如下:
先序遍历为ABCD 后序遍历为BDCA
可能会有以下两种结情况:
代码如下:
def buildTree(self, pre: List[int], post: List[int]) -> TreeNode:
if not pre: return None
root = TreeNode(pre[0])
if len(pre) == 1: return root #!!!!!!!!!!!!!!!!!!!!!!!!!!!
i = post.index(pre[1]) + 1
root.left = self.buildTree(pre[1:i+1], post[:i])
root.right = self.buildTree(pre[i+1:], post[i:-1])
return root