表达式树和查找树的 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. ACM 竞赛高校联盟 练习赛 第二场 B&C

    B. 题解: 枚举约数即可,判断n个数能否填约数的整数倍 #include <iostream> #include <cstring> #include <cstdio& ...

  2. Angular 监听路由变化

    var app = angular.module('Mywind',['ui.router']) //Angular 监听路由变化 function run($ionicPlatform, $loca ...

  3. 如何加快JavaScript的加载与执行

    JS 有个很无语的阻塞特性,就是当浏览器在执行JS 代码时,不能同时做其他任何事情,无论其代码是内嵌的还是外部的. 浏览器在碰到一个引入外部JS 文件的<script>标签时会停下所有工作 ...

  4. git使用笔记(九)操作原理

    By francis_hao    Nov 27,2016   参考[1]的一张图已经把git的基本原理描述的很清楚了,如下:   下面以实例演示其过程,需要用到两个命令cat-file和ls-fil ...

  5. [poj 2104]主席树+静态区间第k大

    题目链接:http://poj.org/problem?id=2104 主席树入门题目,主席树其实就是可持久化权值线段树,rt[i]维护了前i个数中第i大(小)的数出现次数的信息,通过查询两棵树的差即 ...

  6. Educational Codeforces Round 55 (Rated for Div. 2):E. Increasing Frequency

    E. Increasing Frequency 题目链接:https://codeforces.com/contest/1082/problem/E 题意: 给出n个数以及一个c,现在可以对一个区间上 ...

  7. ng 构建

    1.ng 构建和部署 构建:编译和合并ng build 部署:复制dist里面的文件到服务器 2.多环境的支持 配置环境package.json "scripts": { &quo ...

  8. poj 2104 (划分树模板)

    Description You are working for Macrohard company in data structures department. After failing your ...

  9. HDU1166 敌兵布阵(树状数组实现

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  10. 51Nod-1586-约数和

    #include <cstdio> using namespace std; typedef long long ll; ; int n, q; int cnt[MAXN]; ll a[M ...