中缀表达式转化为后缀表达式(使用栈和队列相关知识)

一、题目描述:

        输入一个中缀算术表达式,将其转换为后缀表达式。运算符包括+、-、*、/、(、)、=,参加运算的为小于10的自然数。(只考虑二元运算即可)

输入:

        多组数据,每组数据一行,对应一个算术表达式,每个表达式均以“=”结尾。当表达式只有一个“=”时,输入结束。

输出

        对于每组数据输出一行,为表达式的后缀式。

输入样例1:

9+(3-1)*3+1/2=
1+2=
=

输出样例1:

931-3*+12/+
12+

二、题目来源:

BJFUOJ

三、解题代码:

#include
#include
#include
#include
using namespace std;
int priority[128];//这个数组存+-*/等符号的ASCII码

int main() {
	string str;
	while (1) {
		cin >> str;
		if (str[0] == '=') {
			break;
		}
		//定义优先级
		priority['+'] = 1; priority['-'] = 1;
		priority['*'] = 2; priority['/'] = 2;
		priority['('] = 3; priority[')'] = 3;
		priority['='] = 4;
		queueans;//定义一个名为ans的queue容器来存储字符串,先进先出
		stacksymbols;//定义一个名为symbols的栈来存储char类型的相关数据元素
		int i = 0, start = 0;//start的作用是判断截取操作数的长度
		int n = str.size();//获取输入字符串长度
		while (i < n) {
			while (i < n && priority[str[i]] == 0) {//判断是数字即操作数
				i++;
			}
			if (start < i) {
				ans.push(str.substr(start, i - start));//都是数字的情况,全部放入ans
			}
			if (priority[str[i]]) {//运算数
				if (symbols.empty()) {//若为空,直接入栈
					symbols.push(str[i]);
				}
				else {//不为空,判断
					if (str[i] == ')') {
						while (!symbols.empty() && symbols.top() != '(') {
							string temp = "";//定义一个空的字符串
							temp.push_back(symbols.top());//将symbols中弹出的元素放入temp中
							ans.push(temp);//将temp添加到另一个容器ans中
							symbols.pop();//从symbols中删除这个元素
						}
						symbols.pop();
					}
					else if (symbols.top() == '(' || priority[symbols.top()] < priority[str[i]]) {//如果为(,直接入栈,或优先级低的时候直接入栈
						symbols.push(str[i]);
					}
					else {//如果栈顶元素更大,先出栈
						while (!symbols.empty() && symbols.top() != '(' && priority[symbols.top()] >= priority[str[i]]) {//对现在栈内元素与新来元素优先级进行比较
							string temp = "";//定义一个空的字符串
							temp.push_back(symbols.top());//将symbols中弹出的元素放入temp中
							ans.push(temp);//将temp添加到另一个容器ans中
							symbols.pop();//从symbols中删除这个元素
						}
						symbols.push(str[i]);
					}
				}
			}
			i++;//符号操作完后,i下标后移
			start = i;
		}

		while (!symbols.empty()) {//栈非空
			string temp = "";//定义一个空的字符串
			temp.push_back(symbols.top());//将symbols中弹出的元素放入temp中

			ans.push(temp);//将temp添加到另一个容器ans中
			symbols.pop();//从symbols中删除这个元素		
		}

		while (ans.size() > 0) {
			//if(ans.front()!="=") {
			//	cout << ans.front() << "";
			//	ans.pop();
			//}
			if (ans.front() != "=") {
				cout << ans.front() << "";
			}
			else
			{

			}
			ans.pop();
		}
		//cout << ans.front();
		cout << endl;
	}
	return 0;
}

四、代码详解:

        程序首先通过priority数组定义了各种运算符的优先级,然后使用queue和stack容器来分别存储操作数和运算符。
        程序的核心逻辑部分是一个while循环,它会不断地从标准输入读取字符串。每次读取到一个字符串,程序会处理这个字符串,将其转换为一系列的操作数和运算符。然后,程序会根据运算符的优先级进行计算,并将结果输出到标准输出。
        在处理字符串时,程序首先会跳过所有的非运算符字符,并将连续的操作数保存到ans队列中。当遇到运算符时,程序会根据当前运算符与栈顶运算符的优先级进行操作:

  • 如果栈为空,或当前运算符的优先级大于栈顶运算符的优先级,则将当前运算符入栈。
  • 如果当前运算符的优先级小于等于栈顶运算符的优先级,则将栈顶运算符出栈,并将其加入到ans队列中,直到遇到左括号或当前运算符的优先级大于栈顶运算符的优先级。然后将当前运算符入栈。
  • 如果遇到右括号,则将栈内运算符依次出栈,并加入到ans队列中,直到遇到左括号为止。

        在处理完一个字符串后,程序会将栈内剩余的运算符依次出栈,并加入到ans队列中。最后,程序会依次输出ans队列中的元素,并在输出=时结束。
        这个程序支持基本的加减乘除和括号运算,可以处理比较复杂的数学表达式。

五、基本实现流程:

  • 初始化: 首先定义了一个priority数组,用于存储运算符的优先级。然后定义了三个容器:queue 用于存储操作数和最终结果;stack 用于存储运算符;string 用于存储当前操作数。
  • 读取输入: 使用无限循环,从标准输入读取字符串。程序会不断地处理输入,直到输入为 “=”。
  • 处理字符串:

        遍历字符串的每个字符。
                如果遇到运算符,根据优先级进行处理:入栈、出栈、或直接入栈。
                如果遇到操作数,将其添加到 ans 队列中。
                如果遇到左括号,将其入栈。
                如果遇到右括号,将其对应的左括号之前的运算符依次出栈,并加入到 ans 队列中,直到遇到左括号。

  • 输出结果: 将 ans 队列中的元素依次输出,并在输出 “=” 时结束。

你可能感兴趣的:(数据结构,数据结构,算法)