栈的应用,四则运算解析| 豆包MarsCode AI刷题

64 阅读3分钟

问题描述

小F面临一个编程挑战:实现一个基本的计算器来计算简单的字符串表达式的值。该字符串表达式有效,并可能包含数字(0-9)、运算符+-及括号()。注意,字符串中不包含空格。除法运算应只保留整数结果。请实现一个解析器计算这些表达式的值,且不使用任何内置的eval函数。

测试样例

样例1:

输入:expression = "1+1" 输出:2

样例2:

输入:expression = "3+4*5/(3+2)" 输出:7

样例3:

输入:expression = "4+2*5-2/1" 输出:12

样例4:

输入:expression = "(1+(4+5+2)-3)+(6+8)" 输出:23

样例5:

输入:expression = "2*(5+5*2)/3+(6+8*3)" 输出:40

过程分析

我们学到了栈的存储结构,该结构可以被用来处理这个问题。 首先我们来定义一个栈的结构

typedef struct{ 
ElemType data[MaxSize]; int top;
}SqStack;

接着栈的使用方法。

//顺序栈的初始化:
void InitStack(SqStack &S)
{
	memset(S.data,'\0',MaxSize);
	S.top=-1;
}

//获取栈顶元素(不是出栈操作!!)
bool GetTop(SqStack &S,ElemType &x)
{
	if(S.top==-1)return false;
	x=S.data[S.top];
	return true;
}

//入栈操作:
bool Push(SqStack &S,ElemType x)
{
	if(S.top==(MaxSize-1))return false;
	S.data[++S.top]=x;
	return true;
}

//出栈操作:
bool Pop(SqStack &S,ElemType &x)
{
	if(S.top==-1)return false;
	x=S.data[S.top--];
	return true;
}

做这道题,我们首先要明白怎么存储。 拿一个简单的10%2-3来举例 我们需要将它转变为后缀表达式 即数字正常存储 而符号则根据以下规定存储。

  • 遇到界限符,遇到“(”直接入栈,遇到“)”则将之前的所有操作符弹出,知道遇到“(”
  • 遇到运算符,依次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入后缀表达式,若遇到“(”或栈空则停止,之后再把当前运算符入栈。 按上述步骤做完后,我们就将表达式转化为后缀表达式了。 比如A+B-CD/E+F 就变为了AB+CDE/-F+ 随后的事就交给计算机吧。

我们设定一下关于运算符间的比较大小

bool Priority(char a,char b)
{
	if((a=='+'||a=='-')&&(b=='+'||b=='-'||b=='*'||b=='/'))
	{
		return true;
	}
	else if((a=='*'||a=='/')&&(b=='*'||b=='/'))
	{
		return true;
	}
	return false;
}

接着就是开始计算。 按照上述所说的计算规则,将符号或是操作数逐步压入栈中再进行逐步的计算。 最后我们便可以得出最后的表达式的答案

  • 时间复杂度: O(n),其中 n 是表达式的长度

  • 主要操作是遍历表达式字符串一次

  • 每个字符最多被处理一次

  • 栈操作(push和pop)的时间复杂度是O(1)

  • 递归处理括号时,虽然有递归调用,但每个字符仍然只被处理一次

2. 空间复杂度: O(n)

  • 在最坏情况下(比如表达式中有很多嵌套括号),递归调用栈的深度可能达到O(n)

  • 存储中间结果的栈在最坏情况下也可能需要O(n)的空间