表达式,转换和计算,用C语言描述--Part3

表达式,转换和计算,用C语言描述--Part3
(关于表达式的所有你应该知道的东西)

其余转换

所有剩余的转换都可以轻易地用二分表达式树来完成。事实上,上面的两种转换,也即中缀->前缀和中缀>后缀,也能用二分树来做,但是技巧性太强,而用栈来完成就容易得多。现在我们继续讲解,首先对二分表达式树下一定义。

二分表达式树

表达式树是严格的二分树,叶节点存放操作数,非叶节点存放运算符,根节点存放用于计算左子树和右子树计算结果的运算符。一旦我们得到了某一特定表达式的树,将它转换成各种不同的表示形式(中缀,前缀和后缀)以及计算其值都只需要遍历这棵树就可以了。下图展示了前面的表达式2*3/(2-1)+5*(4-1)对应的表达式树。

 

 

注意:二分表达式树不包含括号,原因在于用树结构计算表达式值的时候,表达式树本身的结构就已经决定了计算的顺序。

当我们先序遍历(先访问根节点,再依次访问左儿子和右儿子)表达式树时,得到的是此表达式的前缀表示,类似地,后序遍历(先依次访问左儿子,右儿子,再访问根节点)将得到后缀表示。如果中序遍历(依次访问左儿子,右儿子,根节点)表达式树我们会得到什么结果呢?对于不包含括号的表达式,中序遍历将得到它的确定的中缀形式,但对那些用括号来改变运算符间优先次序的表达式,简单的中序遍历就不能将其还原成原来的中缀形式。

用表达式树完成各种表示形式间的转换


前缀->中缀
后面的算法适用于其中缀形式中没有用括号来改变运算符间原有优先次序的表达式。
1
)根据前缀表达式创建一棵表达式树
2
)中序遍历这棵树


前缀 ->后缀
1
)根据前缀表达式创建一棵表达式树
2
)后序遍历这棵树


你看这是多么容易啊!关键之处在于根据前缀表达式创建表达式树,下面的算法完成了这项工作:

根据前缀表达式创建表达式树的算法
1)求前缀表达式的逆序
2
)检查输入的下一元素
3
)假如是操作数,则
   i)
创建一个叶节点,也就是没有儿子的节点(node- >left_child=node->right_child=NULL
   ii)
将操作数赋给叶节点的data分量
   iii)
叶节点地址入栈
4
)假如是运算符,则
   i)
创建一个节点
   ii)
运算符赋给该节点的data分量
   iii)
栈顶节点地址出栈,并将其赋值给新节点的left分量,即node->left_child
   iv)
栈顶节点地址出栈,并将其赋值给新节点的right分量,即node->right_child
   v)
新节点地址入栈
5
)假如输入还未结束,跳转到步骤2
6
)假如输入结束,栈中节点地址出栈,此地址即为整个树的根节点地址

前缀表示转换成中缀和后缀表示的算法参考程序#2

后缀->中缀
同前,这里的算法也是只适用于其中缀形式中没有用括号来改变运算符间原有优先次序的表达式。
1
)由后缀表达式创建表达式树
2
)中序遍历该树

后缀->前缀
1
)由后缀表达式创建表达式树
2
)先序遍历该树

根据后缀表达式创建表达式树的算法
1) 检查输入的下一元素
2
)假如是操作数,则
   i
)创建一个叶节点,也就是没有儿子的节点(node- >left_child=node->right_child=NULL
   ii)
将操作数赋给叶节点的data分量
   iii)
叶节点地址入栈
3)
假如是运算符,则
   i)
创建一个节点
   ii)
运算符赋给该节点的data分量
   iii)
栈顶节点地址出栈,并将其赋给新节点的right分量,即node->right_child
   iv)
栈顶节点地址出栈,并将其赋给新节点的left分量,即node->left_child
   v)
新节点地址入栈
4)
假如输入还未结束,跳转到步骤2
5)
假如输入结束,栈中节点地址出栈,此地址即为整个树的根节点地址

上述算法参考程序#2

好了,最终我们可以完称表达式的任意两表示形式的转换了。这里我们对前面的内容作一小节:
1)
中缀->前缀,用栈
2
)中缀->后缀,用栈
3)
前缀->中缀,用表达式树
4)
前缀->后缀,用表达式树
5)
后缀->中缀,用表达式树
6)
后缀->前缀,用表达式树

现在我们所剩下的问题就是如何计算表达式的值了。计算一个表达式的包含两个步骤:
1
)创建给定表达式所对应的二分树
2
)递归地计算这棵树的值
(
按照文中方法,对一个普通的中缀表达式我们要经过中缀->前缀或后缀->表达式树->递归算值的过程。其实也可以用栈直接由中缀形式计算表达式的值――译者注)


下面的函数将用递归的方法计算一个表达式树的值:
函数名:EvaluateTree,参数:根节点地址

 int EvaluateTree (struct node* root)

IF root != NULL
  
  
            IF current node contains an operator
                        x = EvaluateTree(root -> left_child)
                        y = EvaluateTree(root -> right_child)
                        Perform operation on x and y, specified by the 
  
  
                        operator and store result in z
                        Return z
            else Return root->data
  
  

Refer program #2 for evaluation of an Expression Tree.
参考程序#2计算表达式树的值的算法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值