二叉树的先序遍历,中序遍历,后序遍历和层次遍历的Python代码实现

文章目录

      • 0.引言
      • 1.类定义
      • 2.实例化
      • 3.输出和可视化

0.引言

最近学习巩固算法,二叉树的各种遍历经常用到,其中包括二叉树的先序遍历、中序遍历、后序遍历和层次遍历,也顺便定义了计算二叉树高度和叶子节点的函数,最后进行实例化,并利用Graphviz库进行可视化二叉树。
代码是python3,需要可视化的话,要先安装配置Graphviz库(参考:https://blog.csdn.net/MRZHUGH/article/details/107888813)。

1.类定义

# 安装方式 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)

2.实例化

二叉树类定义完成,接下来就二叉树实例化

# 构造二叉树
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)

3.输出和可视化

先序遍历为:
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 

生成了两个文件:
在这里插入图片描述
打开BinaryTree.gv.pdf

二叉树的先序遍历,中序遍历,后序遍历和层次遍历的Python代码实现_第1张图片

Reference:

  • https://pypi.org/project/binarytree/

你可能感兴趣的:(Python,#,数据结构,二叉树,先序遍历,中序遍历,后序遍历,层次遍历)