表達式樹和查找樹的 Python 實現html
目錄node
表達式樹是二叉樹的一種應用,其樹葉是常數或變量,而節點爲操做符,構建表達式樹的過程與後綴表達式的計算相似,只不過在遇到運算符時不是進行計算,而是將樹節點賦值爲運算符,並將節點的左右葉子指向兩個變量構成一個基本的二叉樹後再壓入棧中。ide
Expression Tree: * |___________ | | + * |_____ |_____ | | | | a b c + |__ | | d c
下面利用代碼實現一棵二叉表達式樹函數
完整代碼post
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
接着構建一個表達式樹類,基於二叉樹進行派生,依照構建表達式樹的思路定義一個生成樹的方法code
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()
再定義一個測試函數,以三種遍歷方式遍歷顯示錶達式樹htm
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. 後綴表達式的計算