表达式树和查找树的 Python 实现


目录

  1. 二叉表达式树
  2. 二叉查找树

二叉表达式树

表达式树是二叉树的一种应用,其树叶是常数或变量,而节点为操作符,构建表达式树的过程与后缀表达式的计算类似,只不过在遇到运算符时不是进行计算,而是将树节点赋值为运算符,并将节点的左右叶子指向两个变量构成一个基本的二叉树后再压入栈中

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种情况,

    1. 当删除点为叶子时,直接惰性删除,
    2. 当删除点包含一个叶子时,将节点替换成该叶子
    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 实现的更多相关文章

  1. 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树

    http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...

  2. 数据结构和算法学习笔记十五:多路查找树(B树)

    一.概念 1.多路查找树(multi-way search tree):所谓多路,即是指每个节点中存储的数据可以是多个,每个节点的子节点数也可以多于两个.使用多路查找树的意义在于有效降低树的深度,从而 ...

  3. Python与数据结构[1] -> 栈/Stack[0] -> 链表栈与数组栈的 Python 实现

    栈 / Stack 目录 链表栈 数组栈 栈是一种基本的线性数据结构(先入后出FILO),在 C 语言中有链表和数组两种实现方式,下面用 Python 对这两种栈进行实现. 1 链表栈 链表栈是以单链 ...

  4. (python数据分析)第03章 Python的数据结构、函数和文件

    本章讨论Python的内置功能,这些功能本书会用到很多.虽然扩展库,比如pandas和Numpy,使处理大数据集很方便,但它们是和Python的内置数据处理工具一同使用的. 我们会从Python最基础 ...

  5. 浅谈算法和数据结构: 十 平衡查找树之B树

    前面讲解了平衡查找树中的2-3树以及其实现红黑树.2-3树种,一个节点最多有2个key,而红黑树则使用染色的方式来标识这两个key. 维基百科对B树的定义为“在计算机科学中,B树(B-tree)是一种 ...

  6. 转 浅谈算法和数据结构: 十 平衡查找树之B树

    前面讲解了平衡查找树中的2-3树以及其实现红黑树.2-3树种,一个节点最多有2个key,而红黑树则使用染色的方式来标识这两个key. 维基百科对B树的定义为"在计算机科学中,B树(B-tre ...

  7. Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET

    Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET Python -- 堆数据结构 heapq 分类: Python 2012-09 ...

  8. 数据结构---平衡查找树之B树和B+树(转)

    本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 前面讲解了平衡查找树中的2-3树以及其实现红 ...

  9. 七大查找算法(Python)

    查找算法 -- 简介 查找(Searching)就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素.    查找表(Search Table):由同一类型的数据元素构成的集合    ...

随机推荐

  1. COGS 497——奶牛派对

    奶牛派对 我们发现每头牛需要走的路程即为它到x的最短路+x到它的最短路. 转化: 于是这道题变成了一道典型的单源最短路问题,只需求出每个点到x的最短路dl,以及从x到此点的最短路d2,然后去找max( ...

  2. 计蒜客16495 Truefriend(fwt)

    #include <iostream> #include <cstring> #include <cstdio> using namespace std; type ...

  3. WIN8 打开图片内置管理员无法激活此应用

    1.运行 gpedit.msc 2.计算机配置.windows设置.安全设置.本地策略.安全选项.“用户账户控制用于内置管理员账户的管理员批准模式”  改为已启用 3.重启电脑

  4. bzoj2348

    实在不懂为啥网上的题解都是二分,本人没写二分,wa的很惨结果竟然是printf("%d")的锅,改了就A了 2348: [Baltic 2011]Plagiarism Time L ...

  5. 论文讨论&&思考《Deformable Convolutional Networks》

    这篇论文真是让我又爱又恨,可以说是我看过的最认真也是最多次的几篇paper之一了,首先deformable conv的思想我觉得非常好,通过end-to-end的思想来做这件事也是极其的make se ...

  6. Qt5 界面中文乱码问题

    1.文件所在项目文件  xxx.pro 中添加: QMAKE_CXXFLAGS += -execution-charset:utf- 2.文件以 UTF-8 编码保存 3.添加  utf-8 BOM

  7. Python之日志操作(logging)

    import logging   1.自定义日志级别,日志格式,输出位置 logging.basicConfig( level=logging.DEBUG, format='%(asctime)s | ...

  8. POJ1182 食物链---(经典种类并查集)

    题目链接:http://poj.org/problem?id=1182   食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submission ...

  9. HDU2553 N皇后问题---(dfs)

    http://acm.hdu.edu.cn/showproblem.php?pid=2553 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在 ...

  10. set .net principle

    var ticket = new FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(FormsA ...