1.二叉树的构造,广度/深度遍历
class Node(object):
"""构造结点"""
def __init__(self, item):
self.elem = item
self.lchild = None
self.rchild = None
class Tree(object):
"""构造树"""
def __init__(self):
self.root = None # 从头开始构造 根结点 从下标0 1 2.....
def add(self, item):
node = Node(item)
if self.root is None: # 如果是一棵空树,一个几点都没有
self.root = node
return
queue = [self.root] # 用队列来存放根结点
while queue:
cur_node = queue.pop(0) # 从当前队列的头部读取一个结点,根据该结点是否有左孩子来决定是否在队列尾部添加结点
if cur_node.lchild is None: # 如果没有左孩子,先将结点挂上去,但还没有存入到列表中
cur_node.lchild = node
return
else: # 如果左孩子存在,将左孩子添加到队列的尾部
queue.append(cur_node.lchild)
if cur_node.rchild is None:
cur_node.rchild = node
return
else:
queue.append(cur_node.rchild)
def breadth_travel(self):
"""广度遍历"""
if self.root is None:
return
queue = [self.root]
while queue:
cur_node = queue.pop(0)
print(cur_node.elem, end=" ")
if cur_node.lchild:
queue.append(cur_node.lchild)
if cur_node.rchild:
queue.append(cur_node.rchild)
""" 深度遍历,分以下三种"""
def preorder(self, node):
"""先序遍历"""
if node is None:
return
print(node.elem, end=" ")
self.preorder(node.lchild)
self.preorder(node.rchild)
def inorder(self, node):
"""中序遍历"""
if node is None:
return
self.inorder(node.lchild)
print(node.elem, end=" ")
self.inorder(node.rchild)
def postorder(self, node):
"""后序遍历"""
if node is None:
return
self.postorder(node.lchild)
self.postorder(node.rchild)
print(node.elem, end=" ")
if __name__ == "__main__":
tree = Tree()
tree.add(0)
tree.add(1)
tree.add(2)
tree.add(3)
tree.add(4)
tree.add(5)
tree.add(6)
tree.add(7)
tree.add(8)
tree.add(9)
tree.breadth_travel()
print(" ")
tree.preorder(tree.root) # 传入一个根结点,找到一棵树
print(" ")
tree.inorder(tree.root)
print(" ")
tree.postorder(tree.root)
测试结果
0 1 2 3 4 5 6 7 8 9
0 1 3 7 8 4 9 2 5 6
7 3 8 1 9 4 0 5 2 6
7 8 3 9 4 1 5 6 2 0
改进:深度遍历的另一种递归形式
返回的是数组形式
class Solution:
def preorder(self, root):
"""先序遍历递归形式"""
if not root:
return []
return [root.val] + self.preorder(root.left) + self.preorder(root.right)
def inorder(self, root):
"""中序遍历递归形式"""
if not root:
return []
return self.inorder(root.left) + [root.val] + self.inorder(root.right)
def postorder(self, root):
"""后序遍历递归形式"""
if not root:
return []
return self.postorder(root.left) + self.postorder(root.right) + [root.val]
2. 已知前序和中序,重构二叉树,并打印
先序 根-左-右
中序 左-根-右
后序 左-右-根
先序:[1, 2, 4, 7, 3, 5, 6, 8]
中序:[4, 7, 2, 1, 5, 3, 8, 6]
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
# write code here
if len(pre) > 0:
root = TreeNode(pre[0])
rootindex = tin.index(root.val) # 找出pre的第一个根结点在tin中的索引(位置)
root.left = self.reConstructBinaryTree(pre[1:rootindex+1], tin[:rootindex])
root.right = self.reConstructBinaryTree(pre[rootindex+1:], tin[rootindex+1:])
return root
def breadth_travel(self,root):
newlist = []
if root is None:
return newlist
queue = [root]
while queue:
# 队列前部弹出结点,尾部依次追加左右孩子。弹出的结点放入新建的列表中
cur_node = queue.pop(0)
newlist.append(cur_node.val) # 在队列中弹出一个数,往列表中追加一个数
if cur_node.left:
queue.append(cur_node.left) # 队列尾部追加左右孩子,
if cur_node.right:
queue.append(cur_node.right)
return newlist
# 测试部分
pre = [1, 2, 4, 7, 3, 5, 6, 8]
tin = [4, 7, 2, 1, 5, 3, 8, 6]
s = Solution()
root = s.reConstructBinaryTree(pre, tin) # 根据前中序列,重构二叉树
res = s.breadth_travel(root) # 将重构的而查树通过广度遍历再次打印。
print(res)
结果
[1, 2, 3, 4, 5, 6, 7, 8]
3. 二叉树的深度/高度/宽度
1) 深度
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def TreeDepth(self, pRoot):
# write code here
if not pRoot:
return 0
left = self.TreeDepth(pRoot.left)
right = self.TreeDepth(pRoot.right)
return max(left, right) + 1
# if left >= right:
# return left + 1
# else:
# return right
2) 待更新
4. 树的子结构
方法1:判断B树是否为A树的子结构
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def IsSubtree(self, pRoot1, pRoot2):
# write code here
# 如果2树遍历完都能对应
if not pRoot2:
return True
# 如果pRoot1这棵树遍历完,pRoot2还没遍历完,一定不是
if not pRoot1:
return False
# 如果有节点不等,返回false
if pRoot1.val != pRoot2.val:
return False
# 如果根节点对应的上,那么就分别去子节点里面匹配
return self.IsSubtree(pRoot1.left, pRoot2.left) and self.IsSubtree(pRoot1.right, pRoot2.right)
def HasSubtree(self, pRoot1, pRoot2):
# write code here
result = False
if pRoot1 and pRoot2:
# 以这个根节点为起点判断是否包含
if pRoot1.val == pRoot2.val:
result = self.IsSubtree(pRoot1, pRoot2)
# 如果第一个节点没有匹配上,往下找子节点能否匹配上
if not result:
result = self.HasSubtree(pRoot1.left, pRoot2)
# 如果左子树中匹配不上,就去右子树匹配
if not result:
result = self.HasSubtree(pRoot1.right, pRoot2)
return result
# 测试代码
pRoot1 = TreeNode(8)
pRoot1.left = TreeNode(8)
pRoot1.right = TreeNode(7)
pRoot1.left.left = TreeNode(9)
pRoot1.left.right = TreeNode(2)
pRoot1.right.left = TreeNode(4)
pRoot1.right.right = TreeNode(7)
pRoot2 = TreeNode(8)
pRoot2.left = TreeNode(9)
pRoot2.right = TreeNode(2)
s = Solution()
res = s.HasSubtree(pRoot1, pRoot2)
print(res)
方法2:将结点转换成字符串存储,再判断串2是否在串1内
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def HasSubtree(self, pRoot1, pRoot2):
# write code here
if not pRoot1 or not pRoot2:
return False
# 将两棵树进行先序排列,并转换成字符串
str1 = self.preorder(pRoot1) # '124##5##36##7##'
str2 = self.preorder(pRoot2) # '24##5##'
if str2 in str1:
return True
else:
return False
def preorder(self, root):
res = '' # 构造空字符串
if not root: # 结点一直往下分割,直至该结点下无子结点,就必须有返回值,用#填补
return '#'
res += str(root.val) # 将每一个结点转换成字符串
res += self.preorder(root.left)
res += self.preorder(root.right)
return res