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):由同一类型的数据元素构成的集合 ...
随机推荐
- ashx文件和aspx
ashx文件和aspx文件有什么不同? 我们先新建一个ashx文件看看: <%@ WebHandler Language="C#" Class="Handler&q ...
- bootstrap table表格属性、列属性、事件、方法
留存一份,原文地址http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/ 表格参数 表格的参数定义在 jQuery.fn.bootst ...
- hihoCoder #1872 : Pythagorean triple
此题是 2018 年 ICPC Asia Beijing Regional Contest 的 C 题. 题目大意 求斜边长度不超过 $n$($ n \le 10^9$) 的勾股数的数量.不计两直角边 ...
- TextView AutoLink, ClikSpan 与长按事件冲突的解决
前言 首先,我们先来复习一下 autoLink 和 ClickableSpan 是干什么用的. autoLink 当中有五个属性值:分别是 phone.email.map.web.all 和 none ...
- BZOJ4567 [Scoi2016]背单词 【trie树 + 贪心】
题目链接 BZOJ4567 题解 题意真是鬼畜= = 意思就是说我们应先将一个串的所有后缀都插入之后再插入这个串,产生代价为其到上一个后缀的距离 我们翻转一下串,转化为前缀,就可以建\(trie\)树 ...
- 洛谷 P2414 [NOI2011]阿狸的打字机 解题报告
P2414 [NOI2011]阿狸的打字机 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母 ...
- git查看和操作commit命令
git reflog 显示所有branch的commit,包括commit和reset,以及已删除的commit.而git log只显示当前branch的commit,不包括已删除的commit gi ...
- Treap 模板
感觉平衡树也没有以前想的那么玄乎,(其实set超好用的),非旋式Treap挺好理解,和可并堆,二叉搜索树有很大联系 推荐博客:http://memphis.is-programmer.com/post ...
- 如何用listview显示服务端数据
https://www.cnblogs.com/caobotao/p/5061627.html
- codeforces 1060 B
https://codeforces.com/contest/1060/problem/B 题意:给你一个数C ,你要找到两个数A.B,使得A+B=C并且A的每个位的数的和最大,求最大的和是多少 题解 ...