NOJ8 栈之逆波兰表达式

逆波兰表达式

在这里插入图片描述

将中缀表达式(一个符号连接两个运算符) 转换为后缀表达式 ,( 这样可以保证每次操作数都是后缀表达式中符号前面的两个数 因此方便利用栈的结构 ) ,关键就是按照怎样的顺序转化为中缀表达式

1.首先输出的后缀表达式操作数顺序不变 ,即中缀表达式转化为后缀表达式的重点并不是操作数顺序 ,也不用为操作数建立栈

2.符号顺序会改变 ,且会将运算优先级高的符号更加靠近操作数 ,(可以按照优先级建栈 ,保证栈顶到栈底的优先级由高到低 ,出栈时即优先级高的先输出)

比较top符号和当前符号优先级 ,若当前符号优先级低于top符号则将top符号输出( 先输出保证了更加靠近操作数 ,即优先级高的更先运算 ),然后继续下一个top和当前符号 ,

ps :若当前符号优先级与top优先级相同,则也应该将top输出 ,这样保障了从左到右的运算顺序 ,对加法和乘法来说 ,可以互换顺序 ,而减法和除法必须保证从左到右的运算顺序 ,否则结果错误 ,

a+b-c 则 后缀表达式必须为 ab+c- ,这样就是先输出 + ,

只有遇到符号才开始运算 ,这也保证了运算顺序 ,

最后输出符号的个数是不变的(除了去掉了括号)

3.对括号的处理

若遇到左括号 ,直接将左括号进栈而不必输出任何符号 ,然后对左括号后进栈的元素采取 步骤2 而不必考虑左括号的影响 ,直到遇到右括号则按出栈顺序输出左右括号间的所有内容 ,

a + ( b - c * d - e) * c

a b c d * - e - c * +

#include<bits/stdc++.h>
using namespace std;
struct node {
	char data;
	node* next;
	int level;
};
void pop(node* &top)
{
	if (top == NULL) return;
	node* p = top;
	top = top->next;
	free(p);
}
void push(node*& top, char c)
{
	node* p = (node*)malloc(sizeof(node));
	p->data = c;
	p->next = top;
	top = p;
}
//上面为栈的基本操作

void func1(char c ,node* &top)
{
	node* p;
	if (c >= 'a' && c <= 'z')
	{
		cout << c;
		return;
	}
	
	else if (c == '(')
	{
		push(top, c);
		return;
	}
	else if (c == ')')
	{
		while (top->data != '(')
		{
			cout << top->data;
			pop(top);
		}
		pop(top);
		return;
	}
	else
	{
		p = (node*)malloc(sizeof(node));
		p->data = c;
		if (c == '+' || c == '-')
			p->level = 1;
			
		else if (c == '*' || c == '/')
			p->level = 2;
		while (top!=NULL&&p->level <= top->level)
		{
			cout << top->data;
			pop(top);
		}
		p->next = top;
		top = p;
	}
}
void func()
{
	string s;
	node* top = NULL;
	getline(cin, s);
	int len = s.length();
	for (int i = 0; i < len; i++)
	{
		func1(s[i],top);
	}
	while (top != NULL)
	{
		cout << top->data;
		top = top->next;
	}
}
int main()
{
	func();
}

ps : 除了在node中设置leve选项 ,也可以设置一个函数

int rank(char c)
{
    if(c=='+'||c=='-')	return 1 ;
    else if(c=='*'||c=='/')   return 0 ;
}
然后直接调用函数 rank(top->data) <= rank(c) ;

然后就是计算值 ,这次也只需要建立一个栈 ,将数字和符号放在同一个栈中 ,若top是符号 ,则取出top下面的两个元素 ,计算后返回结果返回top(可以将转换为中缀表达式的输出部分直接转成赋值)

PS :需要考虑的事情:当输入的是数字时 ,若多于一位数 ,接收为string需要转换成数字 ,

可以用字符数组接收每一位,然后转成确定的数字 (可能需要结合大数加减乘除运算)

string s ;
getline(cin,s) ;
int len=s.length() ;
vector<int> a ;
int j=0;
for(int i=0;i<len;i++)
{
   while(s[i]>='0'&&s[i]<='9')
    {
       a[j]+=s[i]-'0' ;
       a[j]*=10 ;
        i++ ;
    }
      a[j]/=10 ;
	  j++ ;   
}
int num = j ;

//更高效的方法 :将while循环的部分加入到判断类型的部分
    

含数字处理的后缀表达式

#include<bits/stdc++.h>
using namespace std;
struct node {
	char data;
	node* next;
	int level;
};
void pop(node*& top)
{
	if (top == NULL) return;
	node* p = top;
	top = top->next;
	free(p);
}
void push(node*& top, char c)
{
	node* p = (node*)malloc(sizeof(node));
	p->data = c;
	p->next = top;
	top = p;
}

void func()
{
	int a[100] = {0};
	string s;
	node* top = NULL;
	getline(cin, s);
	int len = s.length(),j=0;
	for (int i = 0; i < len; i++)
	{
		node* p;
		bool flag = 0;
		if (s[i] >= '0' && s[i] <= '9') flag = 1;
		while (s[i] >= '0' && s[i] <= '9')
		{
			a[j] += s[i] - '0';
			a[j] *= 10;
			i++;
		}
		if (flag == 1)
		{
			a[j] /= 10;
			cout << a[j]<<;
			j++;
		}
		int c = s[i];
		if (c == '(')
		{
			push(top, c);
			return;
		}
		else if (c == ')')
		{
			while (top->data != '(')
			{
				cout << top->data;
				pop(top);
			}
			pop(top);
			return;
		}
		else
		{
			p = (node*)malloc(sizeof(node));
			p->data = c;
			if (c == '+' || c == '-')
				p->level = 1;

			else if (c == '*' || c == '/')
				p->level = 2;
			while (top != NULL && p->level <= top->level)
			{
				cout << top->data;
				pop(top);
			}
			p->next = top;
			top = p;
		}
	}
	while (top != NULL)
	{
		cout << top->data;
		top = top->next;
	}
}
int main()
{
	func();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值