思路:
第一步:中序表达式--->二叉树
第二步:对二叉树进行前序遍历,得到前缀表达式,对二叉树进行后序遍历,得到后缀表达式。
第一步:中序表达式转为二叉树
在上篇文章栈结构与四则运算中提到了通过算术表达式构造二叉树,比如 9+(3-1)*3+10/2
是一个标准的算术表达式,也叫中缀表达式。在通过中缀表达式构造二叉树的过程中,计算数要作为叶子节点,运算符作为中间节点,考虑算术优先级。因为正常单从一个中缀表达式是无法获得唯一的一个二叉树结构的。总结来说,中缀表达式构造二叉树有以下几个步骤和要点:
- 计算数作为叶子节点,运算符作为中间节点。
- 对算式按照优先级和计算顺序分割,计算数为叶子节点,运算符为中间节点,直到算式对应到二叉树中。
- 分析过程中,可以用括号辅助分割表达式,依次分析得到左右树节点(算式中一般常见括号,因此用竖线分隔更好些)。
如下对中缀表达式9+(3-1)*3+10/2
构造二叉树过程:
根据优先级,分为三个部分9
, +
, (3-1)*3+10/2
,计算数9为左叶子,运算符+为中间节点;
继续分割(3-1)*3+10/2
,也是三部分(3-1)*3
,+
,10/2
,+为根节点,左子树为(3-1)*3
,右子树为10/2
继续,先拆分左侧(3-1)*3
,三部分3-1
,*
,3
,* 中间节点,3右叶子,继续可以拆分3-1
;
拆分右侧,对于10/2
,拆分为10
,/
,2
,整个转换完成。
最终的树结构如图
表达式二叉树
第二步,前序和后序遍历
1.前序遍历
图1
对于当前节点,先输出该节点,然后输出他的左孩子,最后输出他的右孩子。以上图为例,递归的过程如下:
(1):输出 1,接着左孩子;
(2):输出 2,接着左孩子;
(3):输出 4,左孩子为空,再接着右孩子;
(4):输出 6,左孩子为空,再接着右孩子;
(5):输出 7,左右孩子都为空,此时 2 的左子树全部输出,2 的右子树为空,此时 1 的左子树全部输出,接着 1 的右子树;
(6):输出 3,接着左孩子;
(7):输出 5,左右孩子为空,此时 3 的左子树全部输出,3 的右子树为空,至此 1 的右子树全部输出,结束。
2.中序遍历
对于当前结点,先输出它的左孩子,然后输出该结点,最后输出它的右孩子。以上图为例:
(1):1-->2-->4,4 的左孩子为空,输出 4,接着右孩子;
(2):6 的左孩子为空,输出 6,接着右孩子;
(3):7 的左孩子为空,输出 7,右孩子也为空,此时 2 的左子树全部输出,输出 2,2 的右孩子为空,此时 1 的左子树全部输出,输出 1,接着 1 的右孩子;
(4):3-->5,5 左孩子为空,输出 5,右孩子也为空,此时 3 的左子树全部输出,而 3 的右孩子为空,至此 1 的右子树全部输出,结束。
3.后序遍历
对于当前结点,先输出它的左孩子,然后输出它的右孩子,最后输出该结点。依旧以上图为例:
(1):1->2->4->6->7,7 无左孩子,也无右孩子,输出 7,此时 6 无左孩子,而 6 的右子树也全部输出,输出 6,此时 4 无左子树,而 4 的右子树全部输出,输出 4,此时 2 的左子树全部输出,且 2 无右子树,输出 2,此时 1 的左子树全部输出,接着转向右子树;
(2):3->5,5 无左孩子,也无右孩子,输出 5,此时 3 的左子树全部输出,且 3 无右孩子,输出 3,此时 1 的右子树全部输出,输出 1,结束。