用栈求前序,中序,后序表达式的值

本文详细介绍了如何将中序表达式转换为前序和后序表达式,并提供了计算这些表达式的方法,包括手动求解和算法实现。中序转前序、后序的结果虽不唯一,但计算结果相同。同时,文章给出了后序和前序表达式的计算步骤,以及中序表达式计算的双栈方法。
摘要由CSDN通过智能技术生成

〇.写在前面

若读者朋友们发现问题,请不吝斧正。

一.中序表达式转前序表达式

以中序表达式: (a + b) * c - d 为例:

  1. 转换之前,我们要通过运算顺序把所有的子表达式按运算顺序都加上括号:
    (a + b) * c - d 变为 (((a + b) * c) - d)

  2. 之后,我们从最外层的括号开始逐步去括号,然后把这一层括号里的运算符移到最前面来:
    (((a + b) * c) - d)
    - ((a + b) * c) d
    - * (a + b) c d
    - * + a b c d

注意:中序转前序或后序的结果不唯一,但计算结果相同,不影响。

二.中序表达式转后序表达式

1.人工求法

中序表达式转后序表达式和转前序表达式是类似的,只不过把运算符放到了最后面。
同样,我们以 (a + b) * c - d 为例:

  1. 加括号:(((a + b) * c) - d)
  2. 逐步去括号:
    ((a + b) * c) d -
    (a + b) c * d -
    a b + c * d -

2.算法(重要)

中序表达式转后序表达式的算法严格来说只需要用到一个栈,但在这里我们用一个栈和一个队列作为辅助。
算法:

1.从前向后遍历中序表达式
2.遍历到的字符是数字,直接入队列
3.遍历到的字符是运算符,则分为两种情况:
(1)如果栈为空或者该运算符的优先级高于或等于栈顶运算符的优先级,入栈;
(2)如果栈不为空且该运算符的优先级低于栈顶运算符的优先级,栈顶运算符出栈,入队列。之后还要判断该运算符的优先级和新栈顶运算符的优先级,即重复3
4.遍历到的字符是括号,也分为两种情况:
(1)左括号,直接入栈;
(2)右括号,把栈顶运算符出栈,入队列。重复此动作,直到栈顶为左括号,左括号出栈,不需要入队列。

以中序表达式 a * b * c + d - e为例
图解如下
在这里插入图片描述

三.后序表达式的计算

后序表达式的计算需要用到一个栈。
算法:

  • 从前往后遍历表达式,遇到数值则入栈。
  • 遇到运算符,则两次出栈,先出栈的做被操作数,后出栈的做操作数。运算结果入栈。
  • 遍历完表达式得到的数就是最后的结果。

举例:
中序表达式:(1 + 4) * 3 - 10 / 5
转换为后序表达式:1 4 + 3 * 10 5 / -
过程如图:结果为13
在这里插入图片描述

四.前序表达式的计算

前序表达式的计算和后序表达式的计算也类似,但有两点不一样:

  • 从后往前遍历,遇到数值则入栈。
  • 遇到运算符,则两次出栈,先出栈的做操作数,后出栈的做被操作数。运算结果入栈。

举例:
中序表达式:(1 + 4) * 3 - 10 / 5
转换为前序表达式:- * + 1 4 3 / 10 5
过程如图:结果为13

在这里插入图片描述

五.中序表达式的计算(重要)

中序表达式的计算需要用到两个栈,存放运算符的那个栈叫做算符栈,存放数字的那个栈叫对象栈。
算法:

  1. 从前往后遍历中序表达式

  2. 遍历到的是数字,入对象栈

  3. 遍历到的是运算符,则分为两种情况:
    (1)如果算符栈为空或者该运算符的优先级高于或等于算符栈栈顶运算符的优先级,入栈;
    (2)如果算符栈不为空且该运算符的优先级低于算符栈栈顶运算符的优先级:
    (3)注意:左括号 ( 的优先级最低。

    1. 算符栈栈顶运算符出栈
    2. 对象栈两次出栈,先出栈的做被操作数,后出栈的做操作数
    3. 把两个数的通过出栈的运算符的计算结果入对象栈
    4. 之后还要判断该运算符的优先级和新栈顶运算符的优先级,即重复3
  4. 遍历到的字符是括号,也分为两种情况:
    (1)左括号,直接入算符栈;
    (2)右括号,把算符栈栈顶运算符出栈,对象栈两次出栈,先出栈的做被操作数,后出栈的做操作数,运算结果入对象栈。重复此动作,直到算符栈栈顶为左括号,最后左括号出栈。

  5. 遍历完后,把算符栈里的运算符依次出栈,直到栈为空。同上文的运算方法,最后对象栈中只剩下一个数,这个数就是最后的结果。

举例:
中序表达式:(1 + 4) * 3 - 10 / 5
过程如图:
在这里插入图片描述

六.代码实现

代码实现:

#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <stack>
using namespace std;

int calc(int num1, int num2, string& ope)
{
   
	if (ope == "+")
		return num1 + num2;
	else if (ope == "-")
		return num1 - num2;
	else if (ope == "*")
		return num1 * num2;
	else
		return num1 / num2;
}

bool my_func_greater(string& c1, string& c2)
{
   
	if (c1 == "(")
		return false;
	//大于
	if ((c1 
下面是利用中序后序表达式建立二叉树的C语言实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 二叉树节点结构体定义 struct TreeNode { char data; // 节点数据 struct TreeNode *left; // 左子树指针 struct TreeNode *right; // 右子树指针 }; // 根据中序后序表达式建立二叉树函数 struct TreeNode* buildTree(char *inorder, char *postorder, int len) { if (len == 0) { // 如果长度为0,则返回NULL return NULL; } // 创建根节点 struct TreeNode *root = (struct TreeNode*)malloc(sizeof(struct TreeNode)); root->data = *(postorder + len - 1); root->left = NULL; root->right = NULL; if (len == 1) { // 如果长度为1,则返回根节点 return root; } // 在中序表达式中查找根节点 char *p = strchr(inorder, root->data); int pos = p - inorder; // 计算根节点在中序表达式中的位置 // 递归构建左子树和右子树 root->left = buildTree(inorder, postorder, pos); root->right = buildTree(inorder + pos + 1, postorder + pos, len - pos - 1); return root; } // 二叉树前序遍历函数 void preorder(struct TreeNode *root) { if (root == NULL) { return; } printf("%c ", root->data); preorder(root->left); preorder(root->right); } int main() { char inorder[] = "DBEAFC"; char postorder[] = "DEBFCA"; int len = strlen(inorder); // 根据中序后序表达式建立二叉树 struct TreeNode *root = buildTree(inorder, postorder, len); // 二叉树前序遍历 printf("前序遍历结果:"); preorder(root); printf("\n"); return 0; } ``` 输出结果: ``` 前序遍历结果:ABDECF ``` 注意事项: 1. 在中序表达式中查找根节点时,可以使用`strchr()`函数,该函数返回指向第一个匹配字符的指针。 2. 在递归构建左子树和右子树时,要注意计算中序表达式后序表达式的起始位置和长度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值