栈解决中缀表达式转后缀表达式_考研复试上机C++——前缀,后缀,中缀表达式相互转换及其运算...

表达式的转换:

1.中缀表达式转前缀表达式或者后缀表达式

  • 1.1 中缀转后缀

利用两个栈即可从中缀符号串转换得到后缀符号串

  • 1.2 中缀转前缀

中缀先转后缀,然后构造表达式树,得到表达式树根节点后,前序、后序遍历即可得到前缀,后缀表达式

2.后缀表达式转中缀表达式或者前缀表达式

最简单,直接构造表达式二叉树,得到表达式树根节点,然后中序遍历和前序遍历即可

3.前缀表达式转中缀表达式或者后缀表达式

最简单,直接构造表达式二叉树,得到表达式树根节点,然后中序遍历和后序遍历即可

准备工作:

  • 定义表达式树结点类型

typedef struct BTNode{...}BTNode

  • 1.中缀表达式转前缀表达式或者后缀表达式

stack<char> k1,k2//初始化一个操作数栈,一个操作符栈

  • 2.后缀表达式转中缀表达式或者前缀表达式

stack<char> k3//初始化一个操作数栈

  • 3.前缀表达式转中缀表达式或者后缀表达式

stack<char> k4//初始化一个操作数栈

接口声明:

  • 1.中缀表达式转前缀表达式或者后缀表达式

int priority(char x)//返回运算符优先级大小,返回格式是int数字

string intopost(string in)//中缀转后缀

  • 2.后缀表达式转中缀表达式或者前缀表达式

BTNode *posttree(string post)//后缀生成二叉树

  • 3.前缀表达式转中缀表达式或者后缀表达式

BTNode *pretree(string post)//前缀生成二叉树

  • 4.遍历函数

void preorder(BTNode *head);

void inorder(BTNode *head);

void postorder(BTNode *head);

算法核心:

  • 1.中缀表达式转后缀

从左到右扫描

  • 操作符在以下情况时入操作符栈
  1. 操作符栈为空
  2. 栈顶为(
  3. 优先级大于栈顶
  4. 优先级小于栈顶时,把运算符栈顶元素弹到操作数栈直到能入栈为止
  • 若遇到(,直接入操作符栈
  • 若遇到),把(与)内的所有元素都弹到操作数栈中,(与)舍去
  • 若遇到操作数,直接进入操作数栈中

最后把操作符内元素全部压入操作数栈

  • 操作数栈内元素全部出栈后逆序输出

2.后缀表达式生成表达式树

从左到右扫描,遇到操作数进入操作数栈,

遇到操作符,操作数栈先后弹出两个操作数n1,n2

n2连到操作符结点的左子树,n1连到操作符结点的右子树,操作符再进栈

最后操作数栈中只有一个操作符,弹出即可得到根节点

3.前缀表达式生成表达式树

从右到左扫描,遇到操作数进入操作数栈,

遇到操作符,操作数栈先后弹出两个操作数n1,n2

n1连到操作符结点的左子树,n2连到操作符结点的右子树,操作符再进栈

最后操作数栈中只有一个操作符,弹出即可得到根节点

#include 

61bc03ff838b9a65fdb149bd8f2c705d.png

表达式的计算:

  • 中缀表达式:先构造表达式树,然后后序遍历生成后缀表达式,再计算
  • 前缀表达式:直接运算
  • 后缀表达式:直接运算

运算整体思路和前缀表达式构造表达式树,后缀表达式构造表达式树一样的

  • 后缀表达式运算

从左到右扫描,遇到操作数进入操作数栈,

遇到操作符,操作数栈先后弹出两个操作数n1,n2

n2 Op n1 得到结果再进栈

最后操作数栈中只有一个结果,弹出即可得到表达式的值

  • 前缀表达式运算

从右到左扫描,遇到操作数进入操作数栈,

遇到操作符,操作数栈先后弹出两个操作数n1,n2

n1 Op n2 得到结果再进栈

最后操作数栈中只有一个结果,弹出即可得到表达式的值

接口声明:

  • 1.操作数栈

stack<double> k;

  • 2.运算函数

double op(double a,double b,char op);

  • 3.后缀表达式运算

double postcalculate(string post);

  • 4.前缀表达式运算

double precalculate(string post);

stack<double> k;
double op(double a,double b,char op);
double postcalculate(string post);
double precalculate(string pre);


double op(double a,double b,char op)
{
	double result;
	switch(op)
	{
		case '*':result=(a*b);break;
	 	case '/':result=(a/b);break;
		case '+':result=(a+b);break;
		case '-':result=(a-b);break;
	};
	return result;
}


//表达式内的数字只能为0-9的整形
double postcalculate(string post)
{
	int i;
	double n1,n2;
	double n3,num;
	for(i=0;i<post.length();i++)
	{
		if(post[i]=='*'||post[i]=='/'||post[i]=='+'||post[i]=='-')
		{
			n1=k.top();
			k.pop();
			n2=k.top();
			k.pop();
			n3=op(n2,n1,post[i]);
			k.push(n3);
		}
		else
		{
			num=post[i]-'0';
			k.push(num);
		}
	}
	n3=k.top();
	k.pop();
	return n3;			
}

//表达式内的数字只能为0-9的整形
double precalculate(string pre)
{
	int i;
	double n1,n2;
	double n3,num;
	for(i=pre.length()-1;i>=0;i--)
	{
		if(pre[i]=='*'||pre[i]=='/'||pre[i]=='+'||pre[i]=='-')
		{
			n1=k.top();
			k.pop();
			n2=k.top();
			k.pop();
			n3=op(n1,n2,pre[i]);
			k.push(n3);
		}
		else
		{
			num=pre[i]-'0';
			k.push(num);
		}
	}
	n3=k.top();
	k.pop();
	return n3;			
}

int main()
{
	string pre="+/236";
    cout<<precalculate(pre)<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值