Python与数据结构[3] -> 树/Tree[1] -> 表达式树和查找树的 Python 实现
表达式树和查找树的 Python 实现
目录
表达式树是二叉树的一种应用,其树叶是常数或变量,而节点为操作符,构建表达式树的过程与后缀表达式的计算类似,只不过在遇到运算符时不是进行计算,而是将树节点赋值为运算符,并将节点的左右叶子指向两个变量构成一个基本的二叉树后再压入栈中。
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(' '))
分段解释
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
查找树是二叉树的另一个应用,其特点在于二叉树节点的值大于左子树节点值,小于右子树节点值,这在查找的时候提供了极大的便利。
Search Tree: 5 |_____ | | 2 7 |__ |__ | | | | 1 3 6 9
二叉树的主要方法及操作思路主要如下:
查找操作:递归查找,若当前值小于查找值则递归查找左子树,大于则右子树,直到查找到目标值或None
插入操作:递归插入,类似于查找,当查找到相同元素时便放弃插入,否则插入到最后查找的位置
删除操作:递归删除,主要有以下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())
分段解释
首先导入二叉树类、树节点类,并定义查找二叉树
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. 后缀表达式的计算