• Python与数据结构[3] -> 树/Tree[1] -> 表达式树和查找树的 Python 实现


    表达式树和查找树的 Python 实现


    目录

    1. 二叉表达式树
    2. 二叉查找树

    二叉表达式树

    表达式树是二叉树的一种应用,其树叶是常数或变量,而节点为操作符,构建表达式树的过程与后缀表达式的计算类似,只不过在遇到运算符时不是进行计算,而是将树节点赋值为运算符,并将节点的左右叶子指向两个变量构成一个基本的二叉树后再压入栈中

    Expression Tree:
        *
        |___________
        |           |
        +           *
        |_____      |_____
        |     |     |     |
        a     b     c     +
                          |__
                          |  |
                          d  c

    下面利用代码实现一棵二叉表达式树

    完整代码

     1 from binary_tree import BinaryTree, TreeNode
     2 from stack.linked_list_stack import Stack
     3 
     4 
     5 class ExpressionTree(BinaryTree):
     6     SIGN = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3}
     7     
     8     def gene_tree_by_postfix(self, expr):
     9         s = Stack()
    10         for i in expr:
    11             if i in self.SIGN.keys():
    12                 right = s.pop()
    13                 left = s.pop()
    14                 node = TreeNode(i, left, right)
    15                 s.push(node)
    16             else:
    17                 s.push(TreeNode(i))
    18         self._root = s.pop()
    19 
    20 
    21 def test_expression_tree(ep):
    22     t = ExpressionTree()
    23     t.gene_tree_by_postfix(ep)
    24     print('
    ------Pre-traversal-------')
    25     print(t)
    26 
    27     print('
    ------Post-traversal------')
    28     t.show(t.post_traversal())
    29     print('
    -------In-traversal-------')
    30     t.show(t.in_traversal())
    31 
    32 
    33 if __name__ == '__main__':
    34     ep = 'a b + c d e + * *'
    35     '''
    36     *
    37     |___________
    38     |           |
    39     +           *
    40     |_____      |_____
    41     |     |     |     |
    42     a     b     c     +
    43                       |__
    44                       |  |
    45                       d  c
    46     '''
    47     test_expression_tree(ep.split(' '))
    View Code

    分段解释

    首先导入二叉树类、树节点类和

    1 from binary_tree import BinaryTree, TreeNode
    2 from stack.linked_list_stack import Stack

    接着构建一个表达式树类,基于二叉树进行派生,依照构建表达式树的思路定义一个生成树的方法

     1 class ExpressionTree(BinaryTree):
     2     SIGN = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3}
     3     
     4     def gene_tree_by_postfix(self, expr):
     5         s = Stack()
     6         for i in expr:
     7             if i in self.SIGN.keys():
     8                 right = s.pop()
     9                 left = s.pop()
    10                 node = TreeNode(i, left, right)
    11                 s.push(node)
    12             else:
    13                 s.push(TreeNode(i))
    14         self._root = s.pop()

    再定义一个测试函数,以三种遍历方式遍历显示表达式树

     1 def test_expression_tree(ep):
     2     t = ExpressionTree()
     3     t.gene_tree_by_postfix(ep)
     4     print('
    ------Pre-traversal-------')
     5     print(t)
     6 
     7     print('
    ------Post-traversal------')
     8     t.show(t.post_traversal())
     9     print('
    -------In-traversal-------')
    10     t.show(t.in_traversal())

    最后输入一个后缀表达式,进行测试

     1 if __name__ == '__main__':
     2     ep = 'a b + c d e + * *'
     3     '''
     4     *
     5     |___________
     6     |           |
     7     +           *
     8     |_____      |_____
     9     |     |     |     |
    10     a     b     c     +
    11                       |__
    12                       |  |
    13                       d  c
    14     '''
    15     test_expression_tree(ep.split(' '))

    显示结果为

    ------Pre-traversal-------
    *
        +
            a
            b
        *
            c
            +
                d
                e
    
    ------Post-traversal------
            a
            b
        +
            c
                d
                e
            +
        *
    *
    
    -------In-traversal-------
            a
        +
            b
    *
            c
        *
                d
            +
                e

    2 二叉查找树

    查找树是二叉树的另一个应用,其特点在于二叉树节点的值大于左子树节点值,小于右子树节点值,这在查找的时候提供了极大的便利。

    Search Tree:
            5
            |_____
            |     |
            2     7
            |__   |__
            |  |  |  |
            1  3  6  9

    二叉树的主要方法及操作思路主要如下:

    查找操作:递归查找,若当前值小于查找值则递归查找左子树,大于则右子树,直到查找到目标值或None

    插入操作:递归插入,类似于查找,当查找到相同元素时便放弃插入,否则插入到最后查找的位置

    删除操作:递归删除,主要有以下3种情况,

      1. 当删除点为叶子时,直接惰性删除,
      2. 当删除点包含一个叶子时,将节点替换成该叶子
      3. 当删除点包含两个叶子或子树时,在删除节点的右子树中查找最小叶子,替换当前节点进行删除

    下面用代码实现一棵查找二叉树,

    完整代码

      1 from binary_tree import TreeNode, BinaryTree
      2 
      3 
      4 class SearchTree(BinaryTree):
      5     """
      6     Search Tree:
      7         5
      8         |_____
      9         |     |
     10         2     7
     11         |__   |__
     12         |  |  |  |
     13         1  3  6  9
     14     """
     15     def find(self, item):
     16         if self._root is None:
     17             return None
     18 
     19         def _find(item, node):
     20             if not node:
     21                 return node
     22             if item < node.value:
     23                 return _find(item, node.left)
     24             elif item > node.value:
     25                 return _find(item, node.right)
     26             else:
     27                 return node
     28         return _find(item, self._root)
     29         
     30     def find_min(self, node=None):
     31         if self._root is None:
     32             return None
     33         if not node:
     34             node = self._root
     35         if node.left:
     36             return self.find_min(node.left)
     37         return node
     38 
     39     def find_max(self, node=None):
     40         if self._root is None:
     41             return None
     42         if not node:
     43             node = self._root
     44         if node.right:
     45             return self.find_max(node.right)
     46         return node
     47 
     48     def find_previous(self, item):
     49         if self._root is None:
     50             return None
     51 
     52         def _find(item, node):
     53             if not node.left and not node.right:
     54                 return None
     55             if item < node.value:
     56                 if item == node.left.value:
     57                     return node
     58                 return _find(item, node.left)
     59             elif item > node.value:
     60                 if item == node.right.value:
     61                     return node
     62                 return _find(item, node.right)
     63         return _find(item, self._root)
     64    
     65     def insert(self, item):
     66         if self._root is None:
     67             self._root = TreeNode(item)
     68             return
     69 
     70         def _insert(item, node):
     71             if not node:
     72                 return TreeNode(item)
     73             if item < node.value:
     74                 node.left = _insert(item, node.left)
     75             elif item > node.value:
     76                 node.right = _insert(item, node.right)
     77             else: pass
     78             return node
     79         self._root = _insert(item, self._root)
     80 
     81     def delete(self, item):
     82         if self._root is None:
     83             return
     84 
     85         def _delete(item, node):
     86             if not node:    # Node no found
     87                 # return None
     88                 raise Exception('Element not in tree.')
     89             if item < node.value:
     90                 node.left = _delete(item, node.left)
     91             elif item > node.value:
     92                 node.right = _delete(item, node.right)
     93             else:   # Node found
     94                 if node.left and node.right:
     95                     # Minimum node in right sub-tree has no left sub-node, can be used to make replacement
     96                     # Find minimum node in right sub-tree
     97                     min_node = self.find_min(node.right)    
     98                     # Replace current node with min_node
     99                     node.value = min_node.value
    100                     # Delete min_node in right sub-tree
    101                     node.right = _delete(min_node.value, node.right)
    102                 else:
    103                     if node.left: 
    104                         node = node.left
    105                     elif node.right:
    106                         node = node.right
    107                     else:
    108                         node = None
    109             return node
    110         self._root = _delete(item, self._root)
    111 
    112 
    113 def test(t):
    114     print('
    Init Search tree:')
    115     for i in [6, 2, 8, 1, 4, 3, 1]:
    116         t.insert(i)
    117     t.show()
    118     print('
    Find min value:')
    119     print(t.find_min())
    120     print('
    Find max value:')
    121     print(t.find_max())
    122     print('
    Find certain value:')
    123     print(t.find(3))
    124     print('
    Find certain value (not exist):')
    125     print(t.find(7))
    126     print('
    Find previous value of certain value:')
    127     print(t.find_previous(3))
    128     print('
    Find previous value of certain value (not exist):')
    129     print(t.find(7))
    130     print('
    Delete certain value (with one sub-node):')
    131     t.delete(4)
    132     t.show()
    133     print('
    Make tree empty:')
    134     t.make_empty()
    135     t.show()
    136     print('
    Init Search tree:')
    137     for i in [6, 2, 8, 1, 5, 3, 4]:
    138         t.insert(i)
    139     t.show()
    140     print('
    Delete certain value (with two sub-node):')
    141     t.delete(2)
    142     t.show()
    143     print('
    Delete certain value (not exist):')
    144     try:
    145         t.delete(7)
    146     except Exception as e:
    147         print(e)
    148     
    149 
    150 if __name__ == '__main__':
    151     test(SearchTree())
    View Code

    分段解释
    首先导入二叉树类、树节点类,并定义查找二叉树

     1 from binary_tree import TreeNode, BinaryTree
     2 
     3 
     4 class SearchTree(BinaryTree):
     5     """
     6     Search Tree:
     7         5
     8         |_____
     9         |     |
    10         2     7
    11         |__   |__
    12         |  |  |  |
    13         1  3  6  9
    14     """

    定义find方法,用于查找元素,以及find_min和find_max方法,用于查找最值,find_previous可以查找到节点的父节点

     1     def find(self, item):
     2         if self._root is None:
     3             return None
     4 
     5         def _find(item, node):
     6             if not node:
     7                 return node
     8             if item < node.value:
     9                 return _find(item, node.left)
    10             elif item > node.value:
    11                 return _find(item, node.right)
    12             else:
    13                 return node
    14         return _find(item, self._root)
    15         
    16     def find_min(self, node=None):
    17         if self._root is None:
    18             return None
    19         if not node:
    20             node = self._root
    21         if node.left:
    22             return self.find_min(node.left)
    23         return node
    24 
    25     def find_max(self, node=None):
    26         if self._root is None:
    27             return None
    28         if not node:
    29             node = self._root
    30         if node.right:
    31             return self.find_max(node.right)
    32         return node
    33 
    34     def find_previous(self, item):
    35         if self._root is None:
    36             return None
    37 
    38         def _find(item, node):
    39             if not node.left and not node.right:
    40                 return None
    41             if item < node.value:
    42                 if item == node.left.value:
    43                     return node
    44                 return _find(item, node.left)
    45             elif item > node.value:
    46                 if item == node.right.value:
    47                     return node
    48                 return _find(item, node.right)
    49         return _find(item, self._root)

    定义insert方法,用于插入元素,定义delete方法,用于删除元素,遵循前面的删除方法。

     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 item < node.value:
    10                 node.left = _insert(item, node.left)
    11             elif item > node.value:
    12                 node.right = _insert(item, node.right)
    13             else: pass
    14             return node
    15         self._root = _insert(item, self._root)
    16 
    17     def delete(self, item):
    18         if self._root is None:
    19             return
    20 
    21         def _delete(item, node):
    22             if not node:    # Node no found
    23                 # return None
    24                 raise Exception('Element not in tree.')
    25             if item < node.value:
    26                 node.left = _delete(item, node.left)
    27             elif item > node.value:
    28                 node.right = _delete(item, node.right)
    29             else:   # Node found
    30                 if node.left and node.right:
    31                     # Minimum node in right sub-tree has no left sub-node, can be used to make replacement
    32                     # Find minimum node in right sub-tree
    33                     min_node = self.find_min(node.right)    
    34                     # Replace current node with min_node
    35                     node.value = min_node.value
    36                     # Delete min_node in right sub-tree
    37                     node.right = _delete(min_node.value, node.right)
    38                 else:
    39                     if node.left: 
    40                         node = node.left
    41                     elif node.right:
    42                         node = node.right
    43                     else:
    44                         node = None
    45             return node
    46         self._root = _delete(item, self._root)

    最后运行测试函数对查找二叉树进行测试,

    初始化一棵树

    1 def test(t):
    2     print('
    Init Search tree:')
    3     for i in [6, 2, 8, 1, 4, 3, 1]:
    4         t.insert(i)
    5     t.show()

    当前树状态为

    Init Search tree:
    6                |       6
        2            |     __|__
            1        |    |     |
            4        |    2     8
                3    |  __|__   
        8            | |     |  
                     | 1     4  
                     |     __|
                     |    |
                     |    3
    

    几种查找元素的基本方法

     1     print('
    Find min value:')
     2     print(t.find_min())
     3     print('
    Find max value:')
     4     print(t.find_max())
     5     print('
    Find certain value:')
     6     print(t.find(3))
     7     print('
    Find certain value (not exist):')
     8     print(t.find(7))
     9     print('
    Find previous value of certain value:')
    10     print(t.find_previous(3))
    11     print('
    Find previous value of certain value (not exist):')
    12     print(t.find(7))

    得到结果

    Find min value:
    1
    
    Find max value:
    8
    
    Find certain value:
    3
    
    Find certain value (not exist):
    None
    
    Find previous value of certain value:
    4
    
    Find previous value of certain value (not exist):
    None

    删除带有一个子节点的元素,惰性删除

    1     print('
    Delete certain value (with one sub-node):')
    2     t.delete(4)
    3     t.show()

    得到结果

    Delete certain value (with one sub-node):
    6           |         6
        2       |       __|__
            1   |      |     |
            3   |      2     8
        8       |    __|  
                |   |  |   |  
                |   1  |   4  
                |      |
                |      |
                |      3

    接着清空树,并重新初始化一棵树

    1     print('
    Make tree empty:')
    2     t.make_empty()
    3     t.show()
    4     print('
    Init Search tree:')
    5     for i in [6, 2, 8, 1, 5, 3, 4]:
    6         t.insert(i)
    7     t.show()

    得到结果

    Make tree empty:
    None
    
    Init Search tree:
    6                   |        6
        2               |      __|__
            1           |     |     |
            5           |     2     8
                3       |   __|__    
                    4   |  |     |
        8               |  1     5
                        |      __|
                        |     |
                        |     3
                        |     |__
                        |        |
                        |        4

    接着删除具有两个子节点的元素2

    1     print('
    Delete certain value (with two sub-node):')
    2     t.delete(2)
    3     t.show()

    得到结果

    Delete certain value (with two sub-node):
    6               |         6     
        3           |       __|__
            1       |      |     |
            5       |      3     8
                4   |    __|__   
        8           |   |     |  
                    |   1     5  
                    |       __|
                    |      |
                    |      4

    最后,尝试删除一个不存在的元素,则会引起报错

    1     print('
    Delete certain value (not exist):')
    2     try:
    3         t.delete(7)
    4     except Exception as e:
    5         print(e)

    得到结果

    Delete certain value (not exist):
    Element not in tree.

    相关阅读


    1. 二叉树

    2.

    3. 后缀表达式的计算

  • 相关阅读:
    谈谈node(1)
    怎么调用html5的摄像头,录音,视频?
    es6-块级作用域let 和 var的区别
    输入手机号自动分隔
    How do I know which version of Javascript I'm using?
    PHP的类中的常量,静态变量的问题。
    【转】马拉松式学习与技术人员的成长性
    JavaScript Prototype in Plain Language
    Promise编程规范
    XMLHttpRequest对象解读
  • 原文地址:https://www.cnblogs.com/stacklike/p/8284878.html
Copyright © 2020-2023  润新知