该篇代码的实现用到了上一篇中定义的栈,和前一篇的目的一样。如果有错误的地方或更好的办法,请不吝赐教,感谢感谢!
树节点的定义:
class tree_Node(object): # 树节点类
def __init__(self,elem):
self.elem = elem
self.left = None
self.right = None
树的定义:
class tree(object):
def __init__(self,root):
root = tree_Node(root)
self.root = root
def put_tree2right(self , tree_temp): # 将tree_temp 树变为 调用树的右孩子
if isinstance(tree_temp , tree):#如果tree_temp 是树类型
self.root.right = tree_temp.root
else:
print("error , this element is a unknown type, please check the expression.")
def put_tree2left(self , tree_temp):# 将tree_temp 树变为 调用树的左孩子
if isinstance(tree_temp , tree): # 如果tree_temp 是树类型
self.root.left = tree_temp.root
else:
print("error , this element is a unknown type, please check the expression.")
def insert_left(self,data): # 为了方便,直接插入到最左端
newNode = tree_Node(data)
temp = self.root
while temp.left is not None:
temp = temp.left
temp.left = newNode
def insert_right(self,data): # 为了方便,直接插入到最右边
newNode = tree_Node(data)
temp = self.root
while temp.right is not None:
temp = temp.right
temp.right = newNode
def pre(self,root_temp):
if root_temp is None:
return
print(root_temp.elem)
self.pre(root_temp.left)
self.pre(root_temp.right)
def preShow(self): # 先序遍历
print(" ========= pre show ========== ")
self.pre(self.root)
def back(self , root_temp):
if root_temp is None:
return
self.back(root_temp.left)
self.back(root_temp.right)
print(root_temp.elem)
def backShow(self):# 后序遍历
print(" ========= back show ========== ")
self.back(self.root)
def mid(self , root_temp):
if root_temp is None:
return
self.mid(root_temp.left)
print(root_temp.elem)
self.mid(root_temp.right)
def change_root_value(self , value):
self.root.elem = value
def midShow(self): # 中序遍历
print(" =========== mid show =================== ")
self.mid(self.root)
测试:
if __name__ == "__main__":
tr = tree(19)
tr.insert_right(13)
tr.insert_right(133)
tr.insert_right(14)
tr.insert_left(10)
tr.insert_left(12)
tr.preShow()
tr.backShow()
tr.midShow()
测试结果如下:
算术表达式树的构造:
其输入是一个后缀表达式,如果想使用常用的中缀表达式,可以参考我python系列的上一篇文章,里面用python实现了中缀表达式转换成后缀表达式。算法基本描述如下:
假设构造a+b+c+d的表达式树:
其后缀表达式为ab+c+d+(依次遍历此序列)
1、a压入栈中
a |
|
|
|
|
2、b压入栈中
a | b |
|
|
|
3、读到 + 时,则将栈中的前两个弹出,新建棵树tree_temp1,+作为根节点,第一个弹出的作为右孩子节点,第二弹出的作为左孩子节点,然后将tree_temp1压入栈中
tree_temp1 |
|
|
|
|
4、c压入栈中
tree_temp1 | c |
|
|
|
5、读到+时,则将栈中的前两个弹出,新建棵树tree_temp2,+作为根节点,第一个弹出的作为右孩子节点,第二弹出的作为左孩子节点,然后将tree_temp2压入栈中
tree_temp2 |
|
|
|
|
6、d压入栈中
tree_temp2 | c |
|
|
|
7、读到+时,则将栈中的前两个弹出,新建棵树tree_temp3,+作为根节点,第一个弹出的作为右孩子节点,第二弹出的作为左孩子节点,然后将tree_temp3压入栈中
tree_temp3 |
|
|
|
|
8、已经遍历完整个字符串,返回tree_temp3(为所求表达式树)
代码实现:
'''
注意:将一棵树连接成另一个点的左子树时,不能将该点的左指针指向这棵树,而是指向这这棵树的根节点。
'''
def judge_cal(string_temp):#判断当前所读的字符是否是运算符
if string_temp in ('+' , '-' , '*' , '/'):
return True
return False
def pruduce_express_tree(express_list):
stack_temp = Stack(100) # 用于临时存储
for str_temp in express_list:
if judge_cal(str_temp) is True:# 如果当前字符为运算符
tree_temp = tree(str_temp) # 新建一个临时的树
if stack_temp.empty() is True: # 判断堆栈是否为空
print("first stack element error,please check your expression(code 1)")
return
right_node = stack_temp.getTop() #将栈顶元素赋给右孩子节点
stack_temp.pop() # 弹出
if stack_temp.empty() is True:#
print("second stack element error,please check your expression(code 2)")
return
left_node = stack_temp.getTop()
stack_temp.pop()
if isinstance(right_node , str): # 如果弹出的是字符串类型,则用正常的方式插入即可
tree_temp.insert_right(right_node)
else: # 反之,将从栈弹出的树的树根作为新树的右孩子
tree_temp.put_tree2right(right_node)
if isinstance(left_node , str): # 左孩子与右孩子类似
tree_temp.insert_left(left_node)
else:
tree_temp.put_tree2left(left_node)
stack_temp.push(tree_temp)
else:
stack_temp.push(str_temp)
return stack_temp.getTop()
测试:
if __name__ == "__main__":
express_list = ['a' , 'b' , '+' ,'c' , 'd' , 'e', '+' , '*' , '*']
print(express_list)
tree_temp = pruduce_express_tree(express_list)
print("============================= ",type(tree_temp))
tree_temp.preShow()
tree_temp.backShow()
tree_temp.midShow()
example_list = ['1' , '12' , '+' , '10' , '2' , '4' , '+' , '*' , '*']
tree_temp = pruduce_express_tree(example_list)
tree_temp.midShow()