最近学习巩固算法,二叉树的各种遍历经常用到,其中包括二叉树的先序遍历、中序遍历、后序遍历和层次遍历,也顺便定义了计算二叉树高度和叶子节点的函数,最后进行实例化,并利用Graphviz库进行可视化二叉树。
代码是python3,需要可视化的话,要先安装配置Graphviz库(参考:https://blog.csdn.net/MRZHUGH/article/details/107888813)。
# 安装方式 pip install graphviz
from graphviz import Digraph
import uuid
from random import sample
"""
定义二叉树类
0.初始化,树存放的数据为data;左子树、右子树为left和right,默认均为None;
1.preorder()函数递归实现二叉树的前序遍历;
2.inorder()函数递归实现二叉树的中序遍历;
3.postorder()函数递归实现二叉树的后序遍历;
4.height()函数计算二叉树的高度;
5.leaves()函数计算二叉树的叶子节点;
6.levelorder函数递归实现二叉树的层序遍历;
7.print_tree函数利用Graphviz库实现二叉树的可视化
"""
# 二叉树类
class BinaryTree(object):
# 初始化
def __init__(self, data = None, left = None, right = None):
# 数据域
self.data = data
# 左子树
self.left = left
# 右子树
self.right = right
self.dot = Digraph(comment = 'Binary Tree')
# 前序遍历
def preorder(self):
if self.data is not None:
print(self.data, end = ' ')
if self.left is not None:
self.left.preorder()
if self.right is not None:
self.right.preorder()
# 中序遍历
def inorder(self):
if self.left is not None:
self.left.inorder()
if self.data is not None:
print(self.data, end = ' ')
if self.right is not None:
self.right.inorder()
# 后序遍历
def postorder(self):
if self.left is not None:
self.left.postorder()
if self.right is not None:
self.right.postorder()
if self.data is not None:
print(self.data, end = ' ')
# 先定义求二叉树高度的函数,后续层序遍历也用得到
# 二叉树高度
def height(self):
# 空的树高度为0,只有root节点的树高度为1
if self.data is None:
return 0
elif self.left is None and self.right is None:
return 1
elif self.left is None and self.right is not None:
return 1 + self.right.height()
elif self.left is not None and self.right is None:
return 1 + self.left.height()
else:
return 1 + max(self.left.height(), self.right.height())
# 定义二叉树的叶子节点函数
def leaves(self):
if self.data is None:
return None
elif self.left is None and self.right is None:
print(self.data, end = ' ')
elif self.left is None and self.right is not None:
self.right.leaves()
elif self.left is not None and self.right is None:
self.left.leaves()
else:
self.left.leaves()
self.right.leaves()
# 层序遍历
def levelorder(self):
# 返回某个节点的左孩子
def left_child_of_Node(node):
return node.left if node.left is not None else None
# 返回某个节点的右孩子
def right_child_of_Node(node):
return node.right if node.right is not None else None
# 层序遍历列表
level_order = []
# 是否添加根节点中的数据
if self.data is not None:
level_order.append([self])
# 获取二叉树的高度
height = self.height()
if height >= 1:
# 对第二层及其以后的层数进行操作,在level_order中添加节点而不是数据
for _ in range(2, height + 1):
# 该层的节点
level = []
for node in level_order[-1]:
# 如果左孩子非空,则添加左孩子
if left_child_of_Node(node):
level.append(left_child_of_Node(node))
# 如果右孩子非空,则添加右孩子
if right_child_of_Node(node):
level.append(right_child_of_Node(node))
# 如果该层非空,则添加该层
if level:
level_order.append(level)
# 遍历后取出每层的数据
# i 是层数
for i in range(0, height):
for index in range(len(level_order[i])):
level_order[i][index] = level_order[i][index].data
return level_order
# 利用Graphviz实现二叉树的可视化
def print_tree(self, save_path = './Binary_Tree.gv', label = False):
# 节点颜色的选择
colors = ['skyblue', 'tomato', 'orange', 'purple', 'green', 'yellow', 'pink', 'red']
# 绘制以某个节点为根节点的二叉树
def print_node(node, node_tag):
# 节点颜色
color = sample(colors, 1)[0]
if node.left is not None:
# 左节点的数据
left_tag = str(uuid.uuid1())
# 左节点
self.dot.node(left_tag, str(node.left.data), style = 'filled', color = color)
# 是否在连接线上写上标签,表明为左子树
label_string = 'L' if label else ' '
# 左节点与其父节点的连线
self.dot.edge(node_tag, left_tag, label = label_string)
print_node(node.left, left_tag)
if node.right is not None:
# 右节点的数据
right_tag = str(uuid.uuid1())
# 右节点
self.dot.node(right_tag, str(node.right.data), style = 'filled', color = color)
# 是否在连接线上写上标签,表明为右子树
label_string = 'R' if label else ' '
# 右节点与其父节点的连线
self.dot.edge(node_tag, right_tag, label = label_string)
print_node(node.right, right_tag)
# 如果树非空
if self.data is not None:
# 根节点标签
root_tag = str(uuid.uuid1())
# 根节点
self.dot.node(root_tag, str(self.data), style = 'filled', color = sample(colors,1)[0])
print_node(self, root_tag)
# 保存文件为指定文件
self.dot.render(save_path)
二叉树类定义完成,接下来就二叉树实例化
# 构造二叉树
right_tree = BinaryTree(6)
right_tree.left = BinaryTree(2)
right_tree.right = BinaryTree(4)
left_tree = BinaryTree(5)
left_tree.left = BinaryTree(1)
left_tree.right = BinaryTree(3)
tree = BinaryTree(11)
tree.left = left_tree
tree.right = right_tree
left_tree = BinaryTree(7)
left_tree.left = BinaryTree(3)
left_tree.right = BinaryTree(4)
# 增加新的变量
right_tree = tree
tree = BinaryTree(18)
tree.left = left_tree
tree.right = right_tree
print('先序遍历为:')
tree.preorder()
print()
print('中序遍历为:')
tree.inorder()
print()
print('后序遍历为:')
tree.postorder()
print()
print('层序遍历为:')
level_order = tree.levelorder()
print(level_order)
print()
height = tree.height()
print('树的高度为%s.' % height)
print('叶子节点为:')
tree.leaves()
print()
# 利用Graphviz进行二叉树的可视化
tree.print_tree(save_path = 'F://Jupyter//BinaryTree.gv', label = True)
先序遍历为:
18 7 3 4 11 5 1 3 6 2 4
中序遍历为:
3 7 4 18 1 5 3 11 2 6 4
后序遍历为:
3 4 7 1 3 5 2 4 6 11 18
层序遍历为:
[[18], [7, 11], [3, 4, 5, 6], [1, 3, 2, 4]]
树的高度为4.
叶子节点为:
3 4 1 3 2 4
Reference: