POJ 1400 Complicated Expressions

本文介绍了一种用于去除数学表达式中多余括号的算法。该算法通过将中缀表达式转换为后缀表达式,然后再转回中缀表达式的方式实现。此方法能有效简化表达式,并保持原有的运算意义不变。

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

Complicated Expressions

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 1543 Accepted: 498

Description

The most important activity of ACM is the GSM network. As the mobile phone operator, ACM must build its own transmitting stations. It is very important to compute the exact behaviour of electro-magnetic waves. Unfortunately, prediction of electro-magnetic fields is a very complex task and the formulas describing them are very long and hard-to-read. For example, below are the Maxwell's Equations describing the basic laws of electrical engineering.

ACM has designed its own computer system that can make some field computations and produce results in the form of mathematic expressions. Unfortunately, by generating the expression in several steps, there are always some unneeded parentheses inside the expression. Your task is to take these partial results and make them "nice" by removing all unnecessary parentheses.

Input

There is a single positive integer T on the first line of input. It stands for the number of expressions to follow. Each expression consists of a single line containing only lowercase letters, operators (+, -, *, /) and parentheses (( and )). The letters are variables that can have any value, operators and parentheses have their usual meaning. Multiplication and division have higher priority then subtraction and addition. All operations with the same priority are computed from left to right (operators are left-associative). There are no spaces inside the expressions. No input line contains more than 250 characters.

Output

Print a single line for every expression. The line must contain the same expression with unneeded parentheses removed. You must remove as many parentheses as possible without changing the semantics of the expression. The semantics of the expression is considered the same if and only if any of the following conditions hold:

  • The ordering of operations remains the same. That means "(a+b)+c" is the same as "a+b+c", and "a+(b/c)" is the same as "a+b/c".
  • The order of some operations is swapped but the result remains unchanged with respect to the addition and multiplication associativity. That means "a+(b+c)" and "(a+b)+c" are the same. We can also combine addition with subtraction and multiplication with division, if the subtraction or division is the second operation. For example, "a+(b-c)" is the same as "a+b-c".

You cannot use any other laws, namely you cannot swap left and right operands and you cannot replace "a-(b-c)" with "a-b+c".

Sample Input

8
(a+(b*c))
((a+b)*c)
(a*(b*c))
(a*(b/c)*d)
((a/(b/c))/d)
((x))
(a+b)-(c-d)-(e/f)
(a+b)+(c-d)-(e+f)

Sample Output

a+b*c
(a+b)*c
a*b*c
a*b/c*d
a/(b/c)/d
x
a+b-(c-d)-e/f
a+b+c-d-(e+f)

分析:就是将中缀表达式转为后缀表达式,再将后缀表达式转换为中缀表达式,用来去掉多于的括号
#include <iostream>
using namespace std;
#include<string>
template <class T>
class stack
{
public:
	stack(int len = 50)
	{
		elem = new T[len];
		m_top = -1;
	}
	~stack()
	{
		delete []elem;
	}
	void Push(const T &val)
	{
		elem[++m_top] = val;
	}
	bool isEmpty()
	{
		return m_top == -1;
	}
	T& Pop() 
	{
		return elem[m_top--];
	}
	T& getTop()
	{
		return elem[m_top];
	}
private:
	T *elem;
	int m_top;
};

int getPriority(char ch)
{
	if(ch == '+' || ch == '-')
		return 1;
	if(ch == '*' || ch == '/')
		return 2;
	return 0;
}
void addBacket(string &str)
{
	string s1 = "(";
	string s2 = ")";
	s1+=str;
	str = s1;
	str+=s2;
}
string InfixtoPostfix(char* exp,int len)
{
	int x = 0;
	string tmpExp;
	stack<char> opStack(len/2);
	for(int i = 0;i<len;i++)
	{
		switch(exp[i])
		{
		case'(':
			opStack.Push(exp[i]);
			break;
		case ')':
			while(opStack.getTop() != '(')
				tmpExp+= opStack.Pop();
			opStack.Pop();
			break;
		case '+':case '-':	case '*':case '/':
			while(!opStack.isEmpty() && opStack.getTop() !='(' &&
				getPriority(opStack.getTop()) >= getPriority(exp[i]))
				tmpExp+= opStack.Pop();
			opStack.Push(exp[i]);
			break;
		default:
			tmpExp+= exp[i];
			break;
		}
	}
	while(!opStack.isEmpty())
	{
		char tmp = opStack.Pop();
		if(tmp != '(')
			tmpExp+= tmp;
	}
	return tmpExp;
}

void PostfixtoInfix(char* exp,int len)
{
	string tmp = InfixtoPostfix(exp,len);
	int x = tmp.length();
	stack<char> op(x);
	stack<string> result(x);
	string tmp1, tmp2;
	for (int i = 0; i < x; i++) 
	{
		if (tmp[i] >= 'a' && tmp[i] <= 'z') 
		{
			op.Push(tmp[i]);
			result.Push(string(1,tmp[i]));
		} 
		else 
		{
			if (getPriority(op.getTop()) != 0 && (getPriority(tmp[i]) > getPriority(op.getTop()) || 
				(getPriority(tmp[i]) == getPriority(op.getTop()) && (tmp[i] == '-' || tmp[i] == '/')))) 
			{
				tmp2 = "(";
				tmp2 += result.getTop();
				tmp2 += ")";
			} else tmp2 = result.getTop();
			result.Pop();
			op.Pop();
			if (getPriority(op.getTop()) != 0 && getPriority(tmp[i]) > getPriority(op.getTop()))
			{
				tmp1 = "(";
				tmp1 += result.getTop();
				tmp1 += ")";
			} else tmp1 = result.getTop();
			op.Pop();
			result.Pop();
			tmp1 += tmp[i];
			tmp1 += tmp2;
			result.Push(tmp1);
			op.Push(tmp[i]);
		}
	}
	cout << result.Pop() << endl;
}
int main()
{
	int num = 0;
	cin>>num;
	while(num--)
	{
		char exp[250];
		cin>>exp;
		PostfixtoInfix(exp,strlen(exp));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值