中缀表达式求值、后缀表达式求值、中缀转后缀、前缀

本文介绍了中缀表达式求值的双栈方法,后缀表达式求值的简单实现,中缀转后缀的转换过程,以及前缀表达式的基本概念。中缀转后缀通过扫描中缀表达式,根据操作符优先级决定进栈或输出。前缀表达式则是从右至左扫描,操作符在操作数之前。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.中缀表达式求值

两个栈:OPND(double类数),OPTR(操作符)。
需要比较栈里和栈外ch的操作符优先级。
运用到atof()函数(stdlib.h),将*char 转换为 double。

#include<iostream>
#include<iomanip>
#include<string.h>
#include<stdlib.h>
using namespace std;
 

#define MAXSIZE 1000

typedef struct
{
	double *base;
	double *top;
	int stacksize;
}SqStack_d;

void Init(SqStack_d &S)
{
	S.base = new double[MAXSIZE];
	S.top = S.base;
	S.stacksize = MAXSIZE;
}

void Push(SqStack_d &S, double e)
{
	if(S.top - S.base != S.stacksize)
	{
		*S.top  = e;
		S.top++;
	}
}

void Pop(SqStack_d &S, double &e)
{
	if(S.top !=S.base)
	{
		S.top--;
		e = *S.top;
	}
}

double GetTop(SqStack_d S)
{
	if(S.base !=S.top)
	{
		return *(S.top-1);
	}
}


typedef struct
{
	char *base;
	char *top;
	int stacksize;
}SqStack_c;

void Init(SqStack_c &S)
{
	S.base = new char[MAXSIZE];
	S.top = S.base;
	S.stacksize = MAXSIZE;
}

void Push(SqStack_c &S, char e)
{
	if(S.top - S.base != S.stacksize)
	{
		*S.top  = e;
		S.top++;
	}
}

void Pop(SqStack_c &S, char &e)
{
	if(S.top !=S.base)
	{
		S.top--;
		e = *S.top;
	}
}

char GetTop(SqStack_c S)
{
	if(S.base !=S.top)
	{
		return *(S.top-1);
	}
}


bool In( char ch)
{
	if(ch>='0'&&ch<='9')
	{
		return true;
	}
	else return false;
}


char Com(char c1,char c2)	//c1:in c2:out or ch
{
	if((c1=='('&&c2==')')||(c1=='='&&c2=='='))
		return '=';
	else if(((c1=='+'||c1=='-')&&(c2=='+'||c2=='-'||c2==')'||c2=='='))||((c1=='*'||c1=='/'||c1==')')&&(c2=='+'||c2=='-'||c2=='*'||c2=='/'||c2==')'||c2=='=')))
		return '>';
	else return '<';
}


double Operate(double a,char x,double b)	//  ASCALL
{
	switch(x)
	{
	case '+':
		return (a+b);
		break;
	case '-':
		return (a-b);
		break;
	case '*':
		return (a*b);
		break;
	case '/':
		return (a/b);
		break;
	}	
}


double Expression(char s[])
{							//  5*(7-3)#
	SqStack_d OPND;
	SqStack_c OPTR;
	Init(OPND);
	Init(OPTR);
	Push(OPTR,'=');	//# 要入栈
	char ch;
	int k=0;
	ch = s[k];	
	double item;
	while(ch != '=' || GetTop(OPTR)!='=')	// GetTop(OPTR)!='=' 防止ch== '=',OPTR中还有操作符
	{
		if(In(ch))	// ch = 4  .5
		{
			char sd[MAXSIZE];
			memset(sd,0,sizeof(sd));
			int i=0;
			while((ch>='0'&&ch<='9')||(ch=='.'))
			{
				sd[i] = ch;
				k++;
				ch = s[k];
				i++;
			}
			item = atof(sd);
			Push(OPND,item);
		}
		else
		{
			switch(Com(GetTop(OPTR),ch))
			{
			case '<':
				{
					Push(OPTR,ch);
					k++;
					ch = s[k];
					break;
				}
			case '>':
				{
					double a,b;
					char op;
					Pop(OPTR,op);
					Pop(OPND,a);
					Pop(OPND,b);
					Push(OPND,Operate(b,op,a));
					break;	// can't cin>>ch
				}
			case '=':
					{
						char x;
						Pop(OPTR,x);
						k++;
						ch = s[k];
						break;
					}
			}
		}
	}
	return GetTop(OPND);
}

int main()
{
	char s[MAXSIZE];
	while(1)
	{
		cin>>s;
		if(s[0] == '=')
			{break;}
		cout<<setiosflags(ios::fixed)<<setprecision(2)<<Expression(s)<<endl;
	}
	return 0;
}

OJ上样例

还待优化:两个栈,如何用一个共享栈,共用体结构;是否可以只用一个char栈

###2. 后缀表达式求值 ###

后缀表达式(从左向右扫描),表达式中的操作符已包含优先级,且无括号操作符,无需再比较优先级。
比中缀表达式简单
一个栈:OPND(double操作数)

#include<iostream>
#include<iomanip>
#include<string.h>
#include<stdlib.h>
using namespace std;
 

#define MAXSIZE 1000

typedef struct
{
	double *base;
	double *top;
	int stacksize;
}SqStack_d;

void Init(SqStack_d &S)
{
	S.base = new double[MAXSIZE];
	S.top = S.base;
	S.stacksize = MAXSIZE;
}

void Push(SqStack_d &S, double e)
{
	if(S.top - S.base != S.stacksize)
	{
		*S.top  = e;
		S.top++;
	}
}

void Pop(SqStack_d &S, double &e)
{
	if(S.top !=S.base)
	{
		S.top--;
		e = *S.top;
	}
}

double GetTop(SqStack_d S)
{
	if(S.base !=S.top)
	{
		return *(S.top-1);
	}
}




double Operate(double a,char x,double b)	//  ASCALL
{
	switch(x)
	{
	case '+':
		return (a+b);
		break;
	case '-':
		return (a-b);
		break;
	case '*':
		return (a*b);
		break;
	case '/':
		return (a/b);
		break;
	}	
}


double Expression(char s[])
{							//  12+=
	SqStack_d OPND;
	Init(OPND);
	char ch;
	int k=0;
	ch = s[0];
	while(ch != '=')	// OPND不足,有剩
	{
		if(ch>='0'&&ch<='9')	
		{
			int flag =1;
			double x;
			x = ch-48;
			Push(OPND,x);
		}
		else
		{
			int flag = 0;
			double a,b;
			Pop(OPND,a);	//2
			Pop(OPND,b);	//1
			Push(OPND,Operate(b,ch,a));
		}
		k++;
		ch = s[k];
	}
	return GetTop(OPND);
}

int main()
{
	char s[MAXSIZE];
	while(1)
	{
		cin>>s;
		if(s[0] == '=')
			{break;}
		cout<<setiosflags(ios::fixed)<<setprecision(2)<<Expression(s)<<endl;
	}
	return 0;
}

这里写图片描述

###3.中缀转后缀###

一个 栈:OPTR(操作符)
从左向右扫描 中缀表达式 :
遇数,输出;
遇符:
栈里<栈外,栈外进栈,输入下一个字符;
栈里==栈外,pop,输入下一个字符;
栈里>栈外,栈里pop,并输出。



#include<iostream>
#include<string>
using namespace std;

#define MAXSIZE 1000

typedef struct
{
	char *base;
	char *top;
	int stacksize;
}SqStack_c;

void Init(SqStack_c &S)
{
	S.base = new char[MAXSIZE];
	S.top = S.base;
	S.stacksize = MAXSIZE;
}

void Push(SqStack_c &S, char e)
{
	if(S.top - S.base != S.stacksize)
	{
		*S.top++ = e;
	}
}

void Pop(SqStack_c &S, char &e)
{
	if(S.top !=S.base)
	{
		S.top--;
		e = *S.top;
	}
}

char GetTop(SqStack_c S)
{
	if(S.base !=S.top)
	{
		return *(S.top-1);
	}
}


char Com(char c1,char c2)
{
	if(((c1=='+'||c1=='-')&&(c2=='+'||c2=='-'||c2==')'||c2=='='))||((c1=='*'||c1=='/'||c1==')')&&(c2=='+'||c2=='-'||c2=='*'||c2=='/'||c2==')'||c2=='=')))
	{
		return '>';
	}
	else if((c1=='='&&c2=='=')||(c1=='('&&c2==')'))
	{
		return '=';
	}
	else
	{
		return '<';
	}
}

void Mid_to_Pos(string s)
{
	SqStack_c OPTR;
	Init(OPTR);
	int k=0;
	char ch = s[0];
	Push(OPTR,'=');
	while(ch!='=' || GetTop(OPTR)!= '=')
	{
		if(ch>='0'&&ch<='9')
		{
			cout<<ch;
			ch = s[++k];
		}
		else
		{
			switch(Com(GetTop(OPTR),ch))
			{
			case '>':
				char e;
				Pop(OPTR,e);
				cout<<e;
				break;
			case '<':
				Push(OPTR,ch);
				ch = s[++k];
				break;
			case '=':
				char x;
				Pop(OPTR,x);
				ch = s[++k];
				break;
			}
		}
	}
	cout<<endl;
}

int main()
{
	while(1)
	{
		string s;
		cin>>s;
		if(s =="=")
		{
			break;
		}
		 Mid_to_Pos(s);
	}
}

这里写图片描述

###4.关于前缀###

中缀表达式“1+((2+3)*4)-5” 转前缀:- + 1 * + 2 3 4 5
前缀求值,中缀转前缀: 与后缀表达式不同之处:从右至左扫描,最终逆序输出(输出时操作符在前,操作数在后。)。

中缀表达式换成前缀表达式(也称为逆波兰表示法),可以利用的数据结构来逐步处理运算符和操作数。以下是使用C++实现的一个简单步骤: 1. 创建一个空。 2. 遍历输入的中缀表达式的每个字符: - 如果遇到数字,将其压入。 - 如果遇到运算符,检查其优先级: - 如果顶元素是左括号、运算符优先级低于当前运算符,则直接将当前运算符压入。 - 否则,从中弹出并连接所有比当前运算符优先级低的操作数,直到遇到左括号,然后将左括号压回,最后将当前运算符压入。 - 如果遇到左括号,直接压入。 - 如果遇到右括号,依次弹出并连接剩余的操作数,直到遇到左括号。 以下是一个简单的C++函数示例,假设`expr`存储了中缀表达式: ```cpp #include <iostream> #include <stack> #include <string> int precedence(char op) { // 按照运算符的优先级排序 if (op == '+' || op == '-') return 1; if (op == '*' || op == '/') return 2; return 0; // 其他运算符如括号无需比较 } std::string infixToPrefix(const std::string& expr) { std::stack<char> prefixStack; for (char c : expr) { if (isdigit(c)) { // 数字直接添加到结果 while (!prefixStack.empty() && !isdigit(prefixStack.top())) { prefixStack.pop(); cout << prefixStack.top(); // 输出操作数 } prefixStack.push(c); } else { while (!prefixStack.empty() && precedence(prefixStack.top()) >= precedence(c)) { // 弹出并添加操作数到结果 cout << prefixStack.top(); prefixStack.pop(); } prefixStack.push(c); // 添加运算符到 } } // 最后处理剩余的所有操作数 while (!prefixStack.empty()) { cout << prefixStack.top(); prefixStack.pop(); } return ""; // 返回前缀表达式字符串,这里仅打印过程,实际返回值需要修改 } int main() { std::string expr = "a+b*(c-d)"; std::cout << "Prefix expression: " << infixToPrefix(expr) << std::endl; return 0; } ``` 在这个例子中,`infixToPrefix`函数会打印出换后的前缀表达式。如果需要作为字符串返回,你需要调整该函数的行为。运行上述程序,可以看到中缀表达式 `a+b*(c-d)` 换成的前缀表达式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值