• Python与数据结构[3] -> 树/Tree[0] -> 二叉树及遍历二叉树的 Python 实现


    二叉树 / Binary Tree


    二叉树是树结构的一种,但二叉树的每一个节点都最多只能有两个子节点。

    Binary Tree:
            00
            |_____
            |     |
            00    00
            |__   |__
            |  |  |  |
            00 00 00 00

    对于二叉树的遍历,主要有以下三种基本遍历方式:

    1. 先序遍历:先显示节点值,再显示左子树和右子树
    2. 中序遍历:先显示左子树,再显示节点值和右子树
    3. 后序遍历:先显示左子树和右子树,再显示节点值

    下面将用代码构建一个二叉树,并实现三种遍历方式,

    完整代码

      1 class TreeNode:
      2     def __init__(self, val=None, lef=None, rgt=None):
      3         self.value = val
      4         self.left = lef
      5         self.right = rgt
      6 
      7     def __str__(self):
      8         return str(self.value)
      9 
     10 
     11 class BinaryTree:
     12     """
     13     Binary Tree:
     14         00
     15         |_____
     16         |     |
     17         00    00
     18         |__   |__
     19         |  |  |  |
     20         00 00 00 00
     21     """
     22     def __init__(self, root=None):
     23         self._root = root
     24 
     25     def __str__(self):
     26         return '
    '.join(map(lambda x: x[1]*4*' '+str(x[0]), self.pre_traversal()))
     27 
     28     def pre_traversal(self, root=None):
     29         if not root:
     30             root = self._root
     31         x = []
     32         depth = -1
     33 
     34         def _traversal(node):
     35             nonlocal depth
     36             depth += 1
     37             x.append((node, depth))
     38             if node and node.left is not None:
     39                 _traversal(node.left)
     40             if node and node.right is not None:
     41                 _traversal(node.right)
     42             depth -= 1
     43             return x
     44         return _traversal(root)
     45 
     46     def in_traversal(self, root=None):
     47         if not root:
     48             root = self._root
     49         x = []
     50         depth = -1
     51 
     52         def _traversal(node):
     53             nonlocal depth
     54             depth += 1
     55             if node and node.left is not None:
     56                 _traversal(node.left)
     57             x.append((node, depth))
     58             if node and node.right is not None:
     59                 _traversal(node.right)
     60             depth -= 1
     61             return x
     62         return _traversal(root)
     63 
     64     def post_traversal(self, root=None):
     65         if not root:
     66             root = self._root
     67         x = []
     68         depth = -1
     69 
     70         def _traversal(node):
     71             nonlocal depth
     72             depth += 1
     73             if node and node.left is not None:
     74                 _traversal(node.left)
     75             if node and node.right is not None:
     76                 _traversal(node.right)
     77             x.append((node, depth))
     78             depth -= 1
     79             return x
     80         return _traversal(root)
     81 
     82     @property
     83     def max_depth(self):
     84         return sorted(self.pre_traversal(), key=lambda x: x[1])[-1][1]
     85 
     86     def show(self, tl=None):
     87         if not tl:
     88             tl = self.pre_traversal()
     89         print('
    '.join(map(lambda x: x[1]*4*' '+str(x[0]), tl)))
     90 
     91     def make_empty(self):
     92         self.__init__()
     93 
     94     def insert(self, item):
     95         if self._root is None:
     96             self._root = TreeNode(item)
     97             return
     98 
     99         def _insert(item, node):
    100             if not node:
    101                 return TreeNode(item)
    102             if node.left is None:
    103                 node.left = _insert(item, node.left)
    104             elif node.right is None:
    105                 node.right = _insert(item, node.right)
    106             else: 
    107                 if len(self.pre_traversal(node.left)) <= len(self.pre_traversal(node.right)):
    108                     node.left = _insert(item, node.left)
    109                 else:
    110                     node.right = _insert(item, node.right)
    111             return node
    112         self._root = _insert(item, self._root)
    113 
    114 
    115 if __name__ == '__main__':
    116     bt = BinaryTree()
    117     print('
    Binary Tree:')
    118     '''
    119     0
    120     |_____
    121     |     |
    122     1     2
    123     |__   |__
    124     |  |  |  |
    125     3  5  4  6 
    126     '''
    127     for i in range(7):
    128         bt.insert(i)
    129     bt.show()
    130     print('
    ------Pre-traversal-------')
    131     print(bt)
    132 
    133     print('
    ------Post-traversal------')
    134     bt.show(bt.post_traversal())
    135     print('
    -------In-traversal-------')
    136     bt.show(bt.in_traversal()) 
    137 
    138     bt.make_empty()
    139     print('
    -------Empty-tree-------')
    140     print(bt)
    View Code

    分段解释

    首先定义树节点,包含3个属性(指针引用),分别为:当前值,左子树节点,右子树节点

    1 class TreeNode:
    2     def __init__(self, val=None, lef=None, rgt=None):
    3         self.value = val
    4         self.left = lef
    5         self.right = rgt
    6 
    7     def __str__(self):
    8         return str(self.value)

    构建一个二叉树类,构造函数中包含一个根节点属性,

     1 class BinaryTree:
     2     """
     3     Binary Tree:
     4         00
     5         |_____
     6         |     |
     7         00    00
     8         |__   |__
     9         |  |  |  |
    10         00 00 00 00
    11     """
    12     def __init__(self, root=None):
    13         self._root = root

    重定义__str__方法,在打印树时,依据树的深度添加tab显示,类似于文件目录(文件分级目录原本便是由树实现的)的显示方式

    1     def __str__(self):
    2         return '
    '.join(map(lambda x: x[1]*4*' '+str(x[0]), self.pre_traversal()))

    定义先序遍历方法,通过递归的方式进行实现,优先显示当前节点

     1     def pre_traversal(self, root=None):
     2         if not root:
     3             root = self._root
     4         x = []
     5         depth = -1
     6 
     7         def _traversal(node):
     8             nonlocal depth
     9             depth += 1
    10             x.append((node, depth))
    11             if node and node.left is not None:
    12                 _traversal(node.left)
    13             if node and node.right is not None:
    14                 _traversal(node.right)
    15             depth -= 1
    16             return x
    17         return _traversal(root)

    定义中序遍历方法,与先序遍历基本相同,只是处理当前节点的顺序在左子树之后,右子树之前,

     1     def in_traversal(self, root=None):
     2         if not root:
     3             root = self._root
     4         x = []
     5         depth = -1
     6 
     7         def _traversal(node):
     8             nonlocal depth
     9             depth += 1
    10             if node and node.left is not None:
    11                 _traversal(node.left)
    12             x.append((node, depth))
    13             if node and node.right is not None:
    14                 _traversal(node.right)
    15             depth -= 1
    16             return x
    17         return _traversal(root)

    定义后序遍历方法,处理当前节点的顺序在左子树和右子树之后,

     1     def post_traversal(self, root=None):
     2         if not root:
     3             root = self._root
     4         x = []
     5         depth = -1
     6 
     7         def _traversal(node):
     8             nonlocal depth
     9             depth += 1
    10             if node and node.left is not None:
    11                 _traversal(node.left)
    12             if node and node.right is not None:
    13                 _traversal(node.right)
    14             x.append((node, depth))
    15             depth -= 1
    16             return x
    17         return _traversal(root)

    再定义一些树的基本方法,显示树的时候,优先采用先序遍历显示,

     1     @property
     2     def max_depth(self):
     3         return sorted(self.pre_traversal(), key=lambda x: x[1])[-1][1]
     4 
     5     def show(self, tl=None):
     6         if not tl:
     7             tl = self.pre_traversal()
     8         print('
    '.join(map(lambda x: x[1]*4*' '+str(x[0]), tl)))
     9 
    10     def make_empty(self):
    11         self.__init__()

    最后定义二叉树的插入方法,插入方式尽量保证二叉树的平衡,插入顺序为当前节点->左->右,当左右节点都不为空时,则递归插入左子树和右子树中,深度较小的那一棵树。

     1     def insert(self, item):
     2         if self._root is None:
     3             self._root = TreeNode(item)
     4             return
     5 
     6         def _insert(item, node):
     7             if not node:
     8                 return TreeNode(item)
     9             if node.left is None:
    10                 node.left = _insert(item, node.left)
    11             elif node.right is None:
    12                 node.right = _insert(item, node.right)
    13             else: 
    14                 if len(self.pre_traversal(node.left)) <= len(self.pre_traversal(node.right)):
    15                     node.left = _insert(item, node.left)
    16                 else:
    17                     node.right = _insert(item, node.right)
    18             return node
    19         self._root = _insert(item, self._root)

    定义完二叉树类后,对二叉树进行构建,插入元素并利用三种遍历方式显示二叉树。

     1 if __name__ == '__main__':
     2     bt = BinaryTree()
     3     print('
    Binary Tree:')
     4     '''
     5     0
     6     |_____
     7     |     |
     8     1     2
     9     |__   |__
    10     |  |  |  |
    11     3  5  4  6 
    12     '''
    13     for i in range(7):
    14         bt.insert(i)
    15     bt.show()
    16     print('
    ------Pre-traversal-------')
    17     print(bt)
    18 
    19     print('
    ------Post-traversal------')
    20     bt.show(bt.post_traversal())
    21     print('
    -------In-traversal-------')
    22     bt.show(bt.in_traversal()) 
    23 
    24     bt.make_empty()
    25     print('
    -------Empty-tree-------')
    26     print(bt)

    三种遍历方式显示结果如下

    Binary Tree:
    0
        1
            3
            5
        2
            4
            6
    
    ------Pre-traversal-------
    0
        1
            3
            5
        2
            4
            6
    
    ------Post-traversal------
            3
            5
        1
            4
            6
        2
    0
    
    -------In-traversal-------
            3
        1
            5
    0
            4
        2
            6
    
    -------Empty-tree-------
    None
  • 相关阅读:
    Android录制视频添加水印的高效方案之YUV帧数据覆盖
    Android 数据库迁移--自定义数据类型
    Android Camera录制视频添加水印
    Android视频录制 花屏、绿屏的分析及解决方案
    Android Moudle封装SDK的步骤及注意事项总结
    Android音频流+视频流合成视频及提取音频流、视频流数据
    常见排序算法以及时间复杂度
    整合两个有序集合 时间复杂度最小为O(n)
    Android启动app步骤简介
    HihoCoder String Matching Content Length
  • 原文地址:https://www.cnblogs.com/stacklike/p/8284691.html
Copyright © 2020-2023  润新知