背景
在学习函数式编程的时候,讲到了二叉树中的前中后序,之前没有听过这几个词,于是去查询了下,在此做下记录。
前序 中序 后序 在二叉树里指的是什么?
在二叉树中,前序、中序和后序指的是三种不同的深度优先遍历(DFS, Depth-First Search)方式。每种遍历方式都规定了访问节点的顺序,具体如下:
-
前序遍历 (Pre-order Traversal):
- 访问顺序为:根节点 -> 左子树 -> 右子树。
- 在遍历过程中,首先访问当前节点(根),然后递归地进行左子树的前序遍历,最后递归地进行右子树的前序遍历。
-
中序遍历 (In-order Traversal):
- 访问顺序为:左子树 -> 根节点 -> 右子树。
- 在遍历过程中,首先递归地进行左子树的中序遍历,然后访问当前节点(根),最后递归地进行右子树的中序遍历。
- 对于二叉搜索树(BST, Binary Search Tree),中序遍历会得到一个节点值按升序排列的序列。
-
后序遍历 (Post-order Traversal):
- 访问顺序为:左子树 -> 右子树 -> 根节点。
- 在遍历过程中,首先递归地进行左子树的后序遍历,然后递归地进行右子树的后序遍历,最后访问当前节点(根)。
这个前 中 后 指的是根节点的访问顺序? 这三种方式 有什么不同吗?为什么要分成这三种?
是的,前序、中序和后序中的“前”、“中”、“后”确实指的是根节点相对于其左右子树被访问的顺序。这三种遍历方式的主要区别在于它们访问根节点的时间点不同,这种不同的访问顺序导致了遍历结果的不同,并且每种遍历方式都有其特定的应用场景。
三种遍历方式的区别
-
前序遍历 (Pre-order Traversal)
- 根 -> 左 -> 右:首先访问根节点,然后是左子树,最后是右子树。
- 应用:前序遍历可以用来复制二叉树,因为它首先处理的是根节点,随后再递归地处理子树。另外,在表达式树(如算术表达式)中,前序遍历可以得到一个前缀表达式(波兰表示法)。
-
中序遍历 (In-order Traversal)
- 左 -> 根 -> 右:先访问左子树,然后是根节点,最后是右子树。
- 应用:对于二叉搜索树(BST),中序遍历会按照从小到大的顺序访问所有节点,因此它常用于获取排序后的元素列表或验证一棵树是否为二叉搜索树。在表达式树中,中序遍历可以得到一个中缀表达式(标准数学表达式格式)。
-
后序遍历 (Post-order Traversal)
- 左 -> 右 -> 根:先访问左子树,然后是右子树,最后访问根节点。
- 应用:后序遍历常用于释放树结构所占用的内存资源,因为只有当子树的所有节点都被处理完毕后,才会处理根节点。在表达式树中,后序遍历可以得到一个后缀表达式(逆波兰表示法),这对于计算表达式的值非常有用,因为不需要考虑操作符的优先级。
为什么需要这三种遍历方式?
-
适应不同的需求:不同的应用场景可能需要以不同的顺序来访问二叉树的节点。例如,如果你想要按升序访问二叉搜索树的元素,那么中序遍历就是最合适的;如果你想要复制一棵树,那么前序遍历就很有用;如果你想要删除一棵树,那么后序遍历可以帮助你安全地从叶子节点开始删除,直到根节点。
-
解决不同类型的问题:某些算法问题要求特定的遍历顺序才能正确解决问题。比如构建二叉树的问题,通常给定中序遍历和前序/后序遍历的结果,你可以重建原始的二叉树。
-
数据结构操作:在实现二叉树的各种操作时,比如查找、插入、删除等,理解并选择正确的遍历方式能够提高效率和简化代码逻辑。
波兰表示法是什么?
波兰表示法(Polish Notation),也称为前缀表示法,是一种用于表示算术表达式的方式。它由波兰逻辑学家扬·武卡谢维奇(Jan Łukasiewicz)在20世纪20年代提出,主要用于逻辑学中,后来也被应用于数学和计算机科学。
波兰表示法的特点
- 操作符前置:在波兰表示法中,操作符总是出现在其操作数之前。例如,普通的中缀表达式
3 + 4在波兰表示法中写作+ 3 4。 - 不需要括号:由于操作符的位置明确指定了操作的顺序,因此波兰表示法不需要使用括号来指定运算的优先级或结合性。这使得解析和计算表达式变得更加简单。
- 易于机器处理:波兰表示法非常适合于计算机处理,因为它可以很容易地通过栈数据结构进行解析和求值,而不需要考虑操作符的优先级。
波兰表示法的例子
- 中缀表达式
3 + 4对应的波兰表示法是+ 3 4。 - 中缀表达式
(3 + 4) * 5对应的波兰表示法是* + 3 4 5。 - 中缀表达式
3 + 4 * 5对应的波兰表示法是+ 3 * 4 5。
波兰表示法的应用
- 编译器设计:编译器在解析程序代码中的表达式时,可能会将中缀表达式转换为波兰表示法(或逆波兰表示法)以简化求值过程。
- 计算器实现:一些高级计算器或编程语言解释器会使用波兰表示法来处理用户输入的表达式,因为这种表示法更容易被机器理解和执行。
- 逻辑学和数学:在某些逻辑系统和数学证明中,波兰表示法提供了一种简洁的方式来书写公式,避免了因括号过多而导致的复杂性和混淆。
逆波兰表示法 (Reverse Polish Notation, RPN)
与波兰表示法相对的是逆波兰表示法(RPN),也称作后缀表示法。在RPN中,操作符位于其操作数之后。例如,中缀表达式 3 + 4 的RPN形式是 3 4 +。RPN同样不需要括号,并且非常容易用栈来实现求值。实际上,很多手持计算器和编程语言(如Forth、PostScript)都使用RPN来处理表达式。
求值方法
对于波兰表示法的表达式求值,通常可以通过递归或使用栈来进行。以下是使用栈求值波兰表示法的一个简单步骤:
- 从右向左读取表达式(因为操作符在前)。
- 如果遇到操作数,则将其压入栈中。
- 如果遇到操作符,则从栈中弹出相应数量的操作数,应用该操作符进行计算,然后将结果压回栈中。
- 当表达式全部读取完毕后,栈顶元素即为表达式的值。
需要注意的是,由于波兰表示法的操作符在前,实际编程中更常用的是逆波兰表示法(RPN),因为它可以直接从左到右扫描表达式并使用栈进行求值,更加直观和方便。