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('\n------Pre-traversal-------')
25     print(t)
26 
27     print('\n------Post-traversal------')
28     t.show(t.post_traversal())
29     print('\n-------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('\n------Pre-traversal-------')
 5     print(t)
 6 
 7     print('\n------Post-traversal------')
 8     t.show(t.post_traversal())
 9     print('\n-------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('\nInit Search tree:')
115     for i in [6, 2, 8, 1, 4, 3, 1]:
116         t.insert(i)
117     t.show()
118     print('\nFind min value:')
119     print(t.find_min())
120     print('\nFind max value:')
121     print(t.find_max())
122     print('\nFind certain value:')
123     print(t.find(3))
124     print('\nFind certain value (not exist):')
125     print(t.find(7))
126     print('\nFind previous value of certain value:')
127     print(t.find_previous(3))
128     print('\nFind previous value of certain value (not exist):')
129     print(t.find(7))
130     print('\nDelete certain value (with one sub-node):')
131     t.delete(4)
132     t.show()
133     print('\nMake tree empty:')
134     t.make_empty()
135     t.show()
136     print('\nInit Search tree:')
137     for i in [6, 2, 8, 1, 5, 3, 4]:
138         t.insert(i)
139     t.show()
140     print('\nDelete certain value (with two sub-node):')
141     t.delete(2)
142     t.show()
143     print('\nDelete 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('\nInit 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('\nFind min value:')
 2     print(t.find_min())
 3     print('\nFind max value:')
 4     print(t.find_max())
 5     print('\nFind certain value:')
 6     print(t.find(3))
 7     print('\nFind certain value (not exist):')
 8     print(t.find(7))
 9     print('\nFind previous value of certain value:')
10     print(t.find_previous(3))
11     print('\nFind 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('\nDelete 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('\nMake tree empty:')
2     t.make_empty()
3     t.show()
4     print('\nInit 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('\nDelete 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('\nDelete 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. 后缀表达式的计算

 

posted @ 2018-01-14 23:36  StackLike  阅读(3247)  评论(0编辑  收藏  举报