逆波兰表达式原理及C++实现

刚开始1.5倍速没看懂小甲鱼说的逆波兰,然后1倍速慢慢听 懂了 emmm 我可能是个小智障 先mark一下 ,睡醒再来写👧

  1. 中缀表达式转后缀表达式
  2. 逆波兰的原理
  3. 上述的实现

首先中缀表达式转后缀表达式的原理:
①优先级的判定
②操作符入栈时,若此时栈顶元素的优先级高于将要入栈的元素X,此时需要将栈内优先级大于等于X优先级的操作符都pop弹出,放在数字的后面
③一对小括号 当操作符遇到“)”时,依次弹出元素,直至遇到匹配的“(”为止

以上就是中缀转后缀的核心思想。

其次逆波兰的核心思想:
检测输入的是数还是字符,将数字压栈,直到遇到操作符,弹出栈顶的两个元素进行计算即可,以下是控制台输入后缀表达式来计算逆波兰的程序代码。(其中通过类模板定义的栈的相关操作代码在前一篇博客中,不再赘述。)

double ReverPolandCalculator()
{	
	string  context;
	Stack<double>S;
	cout << "请输入您想进行计算的数字和运算符 中间以空格分开 以#结束" << endl;
	int count = 0;
	getline(cin, context);//得到用户输入的字符串
	int move = 0;
	char Number[10];
	//数字的最大长度取10 这块没做异常抛出 
	//我寻思 谁也不能整10位数以上的运算把 他不lay么
	while (context[move]!='#')
	{
		if (context[move] !=' ')
		{
			int pos = 0;
			while (isdigit(context[move])|| context[move] == '.')//将数字取出来
			{
				//isdigit() 用来判断字符是否为数字
				Number[pos] = context[move];				
				Number[pos + 1] = '\0';//这个写了是为了后面检测不会出错
				pos++;
				move++;
				//也可直接写为
				//Number[++pos] = '\0';
			}
			if (pos)
			{
				S.PushElem(atof(Number));
			}
			switch (context[move])
			{
			case '-':
			{
				double a = S.PopElem();
				double b = S.PopElem();
				S.PushElem(b - a);
				break;
			}
			case '*':
			{
				double a = S.PopElem();
				double b = S.PopElem();
				S.PushElem(b * a);
				break;
			}
			case '+':
			{
				double a = S.PopElem();
				double b = S.PopElem();
				S.PushElem(b + a);
				break;
			}
			case '/':
			{
				double a = S.PopElem();
				double b = S.PopElem();
				S.PushElem(b / a);
				break;
			}
			default:
				break;
			}
		}
		move++;
	}
	return S.GetTopElem();

}

接着是用户输入中缀表达式转为后缀表达式的代码,睡醒再敲哈哈哈哈哈哈哈哈哈哈💖

double ReverPolandCalculator(char * context)
//重载版本的 直接把中缀转后缀封装到一个测试函数里了 比较的奈斯
//但其实就是把用户输入的字符串换掉了鹅已拉~✨
{	
	Stack<double>S;
	int move = 0;
	char Number[10];//数字的最大长度取10
	while (context[move]!='#')
	{
		if (context[move] !=' ')
		{
			int pos = 0;
			while (isdigit(context[move])|| context[move] == '.')//将数字取出来
			{
				//isdigit() 用来判断字符是否为数字
				Number[pos] = context[move];				
				Number[pos + 1] = '\0';
				pos++;
				move++;
				//也可直接写为
				//Number[pos++] = '\0';
			}
			if (pos)
			{
				S.PushElem(atof(Number));
			}
			switch (context[move])
			{
			case '-':
			{
				double a = S.PopElem();
				double b = S.PopElem();
				S.PushElem(b - a);
				break;
			}
			case '*':
			{
				double a = S.PopElem();
				double b = S.PopElem();
				S.PushElem(b * a);
				break;
			}
			case '+':
			{
				double a = S.PopElem();
				double b = S.PopElem();
				S.PushElem(b + a);
				break;
			}
			case '/':
			{
				double a = S.PopElem();
				double b = S.PopElem();
				S.PushElem(b / a);
				break;
			}
			default:
				break;
			}
		}
		move++;
	}
	return S.GetTopElem();

}
int Priority(char a)
{
	switch (a)
	{
	case '+':
		return 1;
		break;
	case '-':
		return 1;
		break;
	case '*':
		return 2;
		break;
	case '/':
		return 2;
		break;

	default:
		return 0;
		break;
	}



}
char*  Turn2ReverPoland(string context,char *Output)
{



	int i = 0;

	Stack<char>S;
	
	int move = 0;
	while (context[i] != '\0')
	{
		if (isdigit(context[i])|| context[i]=='.')
		{
			Output[move] = context[i];
			Output[move+1] = '\0';
			move++;
			if (isdigit(context[i+1])||context[i+1]=='.')
			{
			}
			else
			{
				move++;
			}
		}
		else
		{
			switch (context[i])
			{
			case ')':
			{
				while ('(' != S.GetTopElem())
				{
					char op1 = S.PopElem();
					Output[move] = op1;
					Output[++move] = '\0';
					move++;
				}
				if ('(' == S.GetTopElem())
				{
					S.PopElem();
				}
				break;
			}
			case '(':
				S.PushElem(context[i]);
				break;
			default:
			{
				int prio = Priority(context[i]);
				if (0==S.GetLength())
				{
					S.PushElem(context[i]);
				}
				else
				{
					while (prio <= Priority(S.GetTopElem()))
					{
						char op1 = S.PopElem();
						Output[move] = op1;
						Output[++move] = '\0';
						move++;
					}
					if (prio > Priority(S.GetTopElem()))
					{
						S.PushElem(context[i]);
					}
					break;

				}

			}
			}
		}
		i++;
	}
	while (S.GetLength())
	{
		Output[move] = S.PopElem();
		Output[++move] = '\0';
		move++;
	}
	Output[move] = '#';
	//a = Output;
	//char *str = Output;

	return Output;


}

然后这些结合食用,就能看见想要的效果拉!
不得不说 模板类真香 C++真香🍭

void ShowReverPoland(char* arr)
{
	int move = 0;
	while (arr[move]!='#')
	{
		cout << arr[move];
		move++;
	}
	cout << endl;
}
void test10()
{
	string context;
	cout << "请输入待计算的表达式:回车结束" << endl;
	getline(cin, context);
	int i = 0;
	char Output[100];
	Turn2ReverPoland(context, Output);
	cout << "逆波兰后的表达式为:" << endl;
	ShowReverPoland(Output);
	double a = ReverPolandCalculator(Output);
	cout << "逆波兰后的计算结果为:"<<a << endl;
}

来个结果~
些许丑陋 emmmm 能用就行 嗨想咋滴👧

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
栈是一种常见的数据结构,用于实现逆波兰表达式求值。逆波兰表达式是一种不需要括号来表示运算优先级的表达式形式,它将操作符放在操作数的后面。 在C++中,可以使用栈来实现逆波兰表达式求值的算法。具体步骤如下: 1. 创建一个空栈,用于存储操作数和中间结果。 2. 从左到右遍历逆波兰表达式的每个元素。 3. 如果当前元素是操作数,则将其入栈。 4. 如果当前元素是操作符,则从栈中弹出两个操作数,并根据操作符进行计算,将计算结果入栈。 5. 重复步骤3和4,直到遍历完所有元素。 6. 最后,栈中剩下的唯一元素就是逆波兰表达式的求值结果。 下面是一个示例的C++代码实现: ```cpp #include <iostream> #include <stack> #include <string> using namespace std; int evaluateRPN(string expression) { stack<int> operands; for (char c : expression) { if (isdigit(c)) { operands.push(c - '0'); } else if (c == '+' || c == '-' || c == '*' || c == '/') { int operand2 = operands.top(); operands.pop(); int operand1 = operands.top(); operands.pop(); int result; switch (c) { case '+': result = operand1 + operand2; break; case '-': result = operand1 - operand2; break; case '*': result = operand1 * operand2; break; case '/': result = operand1 / operand2; break; } operands.push(result); } } return operands.top(); } int main() { string expression = "34+2*"; int result = evaluateRPN(expression); cout << "Result: " << result << endl; return 0; } ``` 这段代码实现了一个简单的逆波兰表达式求值算法。它首先创建了一个栈来存储操作数和中间结果。然后,遍历逆波兰表达式的每个字符,如果是操作数则入栈,如果是操作符则从栈中弹出两个操作数进行计算,并将结果入栈。最后,返回栈中剩下的唯一元素作为求值结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值