Python与数据结构[3] -> 树/Tree[1] -> 表达式树和查找树的 Python 实现
表达式树和查找树的 Python 实现
目录
1 二叉表达式树
表达式树是二叉树的一种应用,其树叶是常数或变量,而节点为操作符,构建表达式树的过程与后缀表达式的计算类似,只不过在遇到运算符时不是进行计算,而是将树节点赋值为运算符,并将节点的左右叶子指向两个变量构成一个基本的二叉树后再压入栈中。
Expression Tree:
*
|___________
| |
+ *
|_____ |_____
| | | |
a b c +
|__
| |
d c
下面利用代码实现一棵二叉表达式树
完整代码
from binary_tree import BinaryTree, TreeNode
from stack.linked_list_stack import Stack class ExpressionTree(BinaryTree):
SIGN = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3} def gene_tree_by_postfix(self, expr):
s = Stack()
for i in expr:
if i in self.SIGN.keys():
right = s.pop()
left = s.pop()
node = TreeNode(i, left, right)
s.push(node)
else:
s.push(TreeNode(i))
self._root = s.pop() def test_expression_tree(ep):
t = ExpressionTree()
t.gene_tree_by_postfix(ep)
print('\n------Pre-traversal-------')
print(t) print('\n------Post-traversal------')
t.show(t.post_traversal())
print('\n-------In-traversal-------')
t.show(t.in_traversal()) if __name__ == '__main__':
ep = 'a b + c d e + * *'
'''
*
|___________
| |
+ *
|_____ |_____
| | | |
a b c +
|__
| |
d c
'''
test_expression_tree(ep.split(' '))
分段解释
from binary_tree import BinaryTree, TreeNode
from stack.linked_list_stack import Stack
接着构建一个表达式树类,基于二叉树进行派生,依照构建表达式树的思路定义一个生成树的方法
class ExpressionTree(BinaryTree):
SIGN = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3} def gene_tree_by_postfix(self, expr):
s = Stack()
for i in expr:
if i in self.SIGN.keys():
right = s.pop()
left = s.pop()
node = TreeNode(i, left, right)
s.push(node)
else:
s.push(TreeNode(i))
self._root = s.pop()
再定义一个测试函数,以三种遍历方式遍历显示表达式树
def test_expression_tree(ep):
t = ExpressionTree()
t.gene_tree_by_postfix(ep)
print('\n------Pre-traversal-------')
print(t) print('\n------Post-traversal------')
t.show(t.post_traversal())
print('\n-------In-traversal-------')
t.show(t.in_traversal())
最后输入一个后缀表达式,进行测试
if __name__ == '__main__':
ep = 'a b + c d e + * *'
'''
*
|___________
| |
+ *
|_____ |_____
| | | |
a b c +
|__
| |
d c
'''
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种情况,
- 当删除点为叶子时,直接惰性删除,
- 当删除点包含一个叶子时,将节点替换成该叶子
- 当删除点包含两个叶子或子树时,在删除节点的右子树中查找最小叶子,替换当前节点进行删除
下面用代码实现一棵查找二叉树,
完整代码
from binary_tree import TreeNode, BinaryTree class SearchTree(BinaryTree):
"""
Search Tree:
5
|_____
| |
2 7
|__ |__
| | | |
1 3 6 9
"""
def find(self, item):
if self._root is None:
return None def _find(item, node):
if not node:
return node
if item < node.value:
return _find(item, node.left)
elif item > node.value:
return _find(item, node.right)
else:
return node
return _find(item, self._root) def find_min(self, node=None):
if self._root is None:
return None
if not node:
node = self._root
if node.left:
return self.find_min(node.left)
return node def find_max(self, node=None):
if self._root is None:
return None
if not node:
node = self._root
if node.right:
return self.find_max(node.right)
return node def find_previous(self, item):
if self._root is None:
return None def _find(item, node):
if not node.left and not node.right:
return None
if item < node.value:
if item == node.left.value:
return node
return _find(item, node.left)
elif item > node.value:
if item == node.right.value:
return node
return _find(item, node.right)
return _find(item, self._root) def insert(self, item):
if self._root is None:
self._root = TreeNode(item)
return def _insert(item, node):
if not node:
return TreeNode(item)
if item < node.value:
node.left = _insert(item, node.left)
elif item > node.value:
node.right = _insert(item, node.right)
else: pass
return node
self._root = _insert(item, self._root) def delete(self, item):
if self._root is None:
return def _delete(item, node):
if not node: # Node no found
# return None
raise Exception('Element not in tree.')
if item < node.value:
node.left = _delete(item, node.left)
elif item > node.value:
node.right = _delete(item, node.right)
else: # Node found
if node.left and node.right:
# Minimum node in right sub-tree has no left sub-node, can be used to make replacement
# Find minimum node in right sub-tree
min_node = self.find_min(node.right)
# Replace current node with min_node
node.value = min_node.value
# Delete min_node in right sub-tree
node.right = _delete(min_node.value, node.right)
else:
if node.left:
node = node.left
elif node.right:
node = node.right
else:
node = None
return node
self._root = _delete(item, self._root) def test(t):
print('\nInit Search tree:')
for i in [6, 2, 8, 1, 4, 3, 1]:
t.insert(i)
t.show()
print('\nFind min value:')
print(t.find_min())
print('\nFind max value:')
print(t.find_max())
print('\nFind certain value:')
print(t.find(3))
print('\nFind certain value (not exist):')
print(t.find(7))
print('\nFind previous value of certain value:')
print(t.find_previous(3))
print('\nFind previous value of certain value (not exist):')
print(t.find(7))
print('\nDelete certain value (with one sub-node):')
t.delete(4)
t.show()
print('\nMake tree empty:')
t.make_empty()
t.show()
print('\nInit Search tree:')
for i in [6, 2, 8, 1, 5, 3, 4]:
t.insert(i)
t.show()
print('\nDelete certain value (with two sub-node):')
t.delete(2)
t.show()
print('\nDelete certain value (not exist):')
try:
t.delete(7)
except Exception as e:
print(e) if __name__ == '__main__':
test(SearchTree())
分段解释
首先导入二叉树类、树节点类,并定义查找二叉树
from binary_tree import TreeNode, BinaryTree class SearchTree(BinaryTree):
"""
Search Tree:
5
|_____
| |
2 7
|__ |__
| | | |
1 3 6 9
"""
定义find方法,用于查找元素,以及find_min和find_max方法,用于查找最值,find_previous可以查找到节点的父节点
def find(self, item):
if self._root is None:
return None def _find(item, node):
if not node:
return node
if item < node.value:
return _find(item, node.left)
elif item > node.value:
return _find(item, node.right)
else:
return node
return _find(item, self._root) def find_min(self, node=None):
if self._root is None:
return None
if not node:
node = self._root
if node.left:
return self.find_min(node.left)
return node def find_max(self, node=None):
if self._root is None:
return None
if not node:
node = self._root
if node.right:
return self.find_max(node.right)
return node def find_previous(self, item):
if self._root is None:
return None def _find(item, node):
if not node.left and not node.right:
return None
if item < node.value:
if item == node.left.value:
return node
return _find(item, node.left)
elif item > node.value:
if item == node.right.value:
return node
return _find(item, node.right)
return _find(item, self._root)
定义insert方法,用于插入元素,定义delete方法,用于删除元素,遵循前面的删除方法。
def insert(self, item):
if self._root is None:
self._root = TreeNode(item)
return def _insert(item, node):
if not node:
return TreeNode(item)
if item < node.value:
node.left = _insert(item, node.left)
elif item > node.value:
node.right = _insert(item, node.right)
else: pass
return node
self._root = _insert(item, self._root) def delete(self, item):
if self._root is None:
return def _delete(item, node):
if not node: # Node no found
# return None
raise Exception('Element not in tree.')
if item < node.value:
node.left = _delete(item, node.left)
elif item > node.value:
node.right = _delete(item, node.right)
else: # Node found
if node.left and node.right:
# Minimum node in right sub-tree has no left sub-node, can be used to make replacement
# Find minimum node in right sub-tree
min_node = self.find_min(node.right)
# Replace current node with min_node
node.value = min_node.value
# Delete min_node in right sub-tree
node.right = _delete(min_node.value, node.right)
else:
if node.left:
node = node.left
elif node.right:
node = node.right
else:
node = None
return node
self._root = _delete(item, self._root)
最后运行测试函数对查找二叉树进行测试,
初始化一棵树
def test(t):
print('\nInit Search tree:')
for i in [6, 2, 8, 1, 4, 3, 1]:
t.insert(i)
t.show()
当前树状态为
Init Search tree:
6 | 6
2 | __|__
1 | | |
4 | 2 8
3 | __|__
8 | | |
| 1 4
| __|
| |
| 3
几种查找元素的基本方法
print('\nFind min value:')
print(t.find_min())
print('\nFind max value:')
print(t.find_max())
print('\nFind certain value:')
print(t.find(3))
print('\nFind certain value (not exist):')
print(t.find(7))
print('\nFind previous value of certain value:')
print(t.find_previous(3))
print('\nFind previous value of certain value (not exist):')
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
删除带有一个子节点的元素,惰性删除
print('\nDelete certain value (with one sub-node):')
t.delete(4)
t.show()
得到结果
Delete certain value (with one sub-node):
6 | 6
2 | __|__
1 | | |
3 | 2 8
8 | __|
| | | |
| 1 | 4
| |
| |
| 3
接着清空树,并重新初始化一棵树
print('\nMake tree empty:')
t.make_empty()
t.show()
print('\nInit Search tree:')
for i in [6, 2, 8, 1, 5, 3, 4]:
t.insert(i)
t.show()
得到结果
Make tree empty:
None Init Search tree:
6 | 6
2 | __|__
1 | | |
5 | 2 8
3 | __|__
4 | | |
8 | 1 5
| __|
| |
| 3
| |__
| |
| 4
接着删除具有两个子节点的元素2
print('\nDelete certain value (with two sub-node):')
t.delete(2)
t.show()
得到结果
Delete certain value (with two sub-node):
6 | 6
3 | __|__
1 | | |
5 | 3 8
4 | __|__
8 | | |
| 1 5
| __|
| |
| 4
最后,尝试删除一个不存在的元素,则会引起报错
print('\nDelete certain value (not exist):')
try:
t.delete(7)
except Exception as e:
print(e)
得到结果
Delete certain value (not exist):
Element not in tree.
相关阅读
1. 二叉树
2. 栈
3. 后缀表达式的计算
Python与数据结构[3] -> 树/Tree[1] -> 表达式树和查找树的 Python 实现的更多相关文章
- 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树
http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...
- 数据结构和算法学习笔记十五:多路查找树(B树)
一.概念 1.多路查找树(multi-way search tree):所谓多路,即是指每个节点中存储的数据可以是多个,每个节点的子节点数也可以多于两个.使用多路查找树的意义在于有效降低树的深度,从而 ...
- Python与数据结构[1] -> 栈/Stack[0] -> 链表栈与数组栈的 Python 实现
栈 / Stack 目录 链表栈 数组栈 栈是一种基本的线性数据结构(先入后出FILO),在 C 语言中有链表和数组两种实现方式,下面用 Python 对这两种栈进行实现. 1 链表栈 链表栈是以单链 ...
- (python数据分析)第03章 Python的数据结构、函数和文件
本章讨论Python的内置功能,这些功能本书会用到很多.虽然扩展库,比如pandas和Numpy,使处理大数据集很方便,但它们是和Python的内置数据处理工具一同使用的. 我们会从Python最基础 ...
- 浅谈算法和数据结构: 十 平衡查找树之B树
前面讲解了平衡查找树中的2-3树以及其实现红黑树.2-3树种,一个节点最多有2个key,而红黑树则使用染色的方式来标识这两个key. 维基百科对B树的定义为“在计算机科学中,B树(B-tree)是一种 ...
- 转 浅谈算法和数据结构: 十 平衡查找树之B树
前面讲解了平衡查找树中的2-3树以及其实现红黑树.2-3树种,一个节点最多有2个key,而红黑树则使用染色的方式来标识这两个key. 维基百科对B树的定义为"在计算机科学中,B树(B-tre ...
- Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET
Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET Python -- 堆数据结构 heapq 分类: Python 2012-09 ...
- 数据结构---平衡查找树之B树和B+树(转)
本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 前面讲解了平衡查找树中的2-3树以及其实现红 ...
- 七大查找算法(Python)
查找算法 -- 简介 查找(Searching)就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素. 查找表(Search Table):由同一类型的数据元素构成的集合 ...
随机推荐
- 使用def文件简化dll导出
原文链接地址:http://www.cnblogs.com/TianFang/archive/2013/05/04/3059073.html 在C++中,我们可以通过 __declspec(dllex ...
- 获取本地ip地址 C#
与ipconfig获取的所有信息一致的方法: private void GetIp() { System.Diagnostics.Process cmdp= new System.Diagnostic ...
- 如何在数据访问层上提高js的执行效率
本文讲到的是如何从数据访问层面上提高JS 代码的执行效率.总的来讲有以下几条原则: 函数中读写局部变量总是最快的,而全局变量的读取则是最慢的: 尽可能地少用with 语句,因为它会增加with 语句以 ...
- JavaScript渐变效果的实现
鼠标移上去透明度渐渐增加,鼠标移出,透明度渐渐减小. 关键代码: view source print? 1 var speed = 0; 2 if(target>obj.alpha){ 3 ...
- 解决echarts中X轴文字过长的问题。【转】
axisLabel: { interval: , formatter:function(value) { debugger var ret = "";//拼接加\n返回的类目项 ; ...
- javascript中Date使用总结(转)
//全局函数 Date //Date 类的静态方法 Date.parse Date.UTC //Date 对象的建立方法 new Date() new Date(毫秒数) new Date(标准时间格 ...
- Android百度地图的使用
做关于位置或者定位的app的时候免不了使用地图功能,本人最近由于项目的需求需要使用百度地图的一些功能,所以这几天研究了一下,现写一下blog记录一下,欢迎大家评论指正! 一.申请AK(API Key) ...
- 2017年上海金马五校程序设计竞赛:Problem C : Count the Number (模拟)
Description Given n numbers, your task is to insert '+' or '-' in front of each number to construct ...
- [bzoj2594][Wc2006]水管局长数据加强版——lct+离线
Brief Description 您有一个无向带权图,您需要支持两种操作. 询问两个点之间的最大权最小路径. 删除一条边. Algorithm Design 我们首先提出一个猜想:最优路径一定在原图 ...
- bzoj 2190 线性生成欧拉函数表
首先我们知道,正方形内个是对称的,关于y=x对称,所以只需要算出来一半的人数 然后乘2+1就行了,+1是(1,1)这个点 开始我先想的递推 那么我们对于一半的三角形,一列一列的看,假设已经求好了第I- ...