#include <iostream>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
#include <cctype>
using namespace std;
const int MAX=1000;//单个数的最大位数
bool is_data(char ch)
{
return (isdigit(ch) || ch=='.');
}
bool is_op(char ch)
{
return (ch=='+' || ch=='-' || ch=='*' || ch=='/');
}
double to_data(char *ch)
{
double sum=0.0;
size_t i,j;
for(i=0;i<strlen(ch);i++)
{
if(ch[i]!='.')
sum=sum*10.0+(ch[i]-'0');
else break;
}
for (j=i+1;j<strlen(ch);j++)
sum=sum+(ch[j]-'0')/(pow(10.0,(double)j-i));
return sum;
}
void get_infix_expre(char* ch,deque<char>& infix_expre,deque<double>& data)
{
char tmp[MAX];
size_t ct=0,tp=0;
bool sign_bit=false;//负数标志
while(ct<strlen(ch))
{
if(ct==0 && ch[ct]=='-')//第一个数为负数
{
sign_bit=true;
ct++;
}
if(ct>0 && ch[ct-1]=='(' && ch[ct]=='-')//左括号'('后的第一个数为负数
{
sign_bit=true;
ct++;
}
if (is_data(ch[ct]))//数据
{
while(ct<strlen(ch) && is_data(ch[ct]))
tmp[tp++]=ch[ct++];
tmp[tp]='\0';
tp=0;
double d=to_data(tmp);
d*=sign_bit?(-1):1;
data.push_back(d);
sign_bit=false;
infix_expre.push_back('#');
}
else//符号
infix_expre.push_back(ch[ct++]);
}
}
int get_pri(char c) //获得符号的优先性
{
switch(c)
{
case '+':
case '-':
return 0; //如果是加减,返回0
break;
case '*':
case '/':
return 1; //如果是乘除,返回1
break;
case '(':
case ')':
return -1; //注意,这里将括号设为最低优先级,因此括号不会被弹出,除非遇到右括号
break;
}
}
//======================================================================================================
/*
中缀表达式转为后缀表达式算法描述:
(1)首先有个包含中缀表达式元素队列infix_expre,一个元素队列postfix_expre保存最终后缀表达式,创建一个
操作符堆栈symbol
(2)从infix_expre取出一个元素A
(3a)如是数字则加入到postfix_expre中
(3b)如果元素A是运算符,将操作符A与操作符堆栈symbol栈顶的运算符的优先关系相比较。如果,优先关系
高于symbol栈顶的运算符,则将该运算符压入操作符堆栈symbol。倘若不是(低于或等于)的话,则将运算
符栈symbol栈顶的运算符从栈中弹出保存到postfix_expre,重复此步骤,直到作符A压入操作符堆栈symbol。
(3c)若元素A是左括号"(",则压入操作符堆栈symbol
(3d)若元素B是右括号")",则操作符堆栈symbol弹出操作符并加入到postfix_expre中,直到弹出左括号"("。
(5)从步骤2重复上述操作,所有元素处理完毕后将操作符堆栈symbol弹出操作符并加入到postfix_expre中,这
样中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
示例:
中缀表达式如 1+2*(3-4)+5,构造元素队列infix_expre1,+,2,*,(,3,-,4,),5。
1. 取出“1”: postfix_expre【1】,symbol【】
2. 取出“+”: postfix_expre【1】,symbol【+】
3. 取出“2”: postfix_expre【1,2】,symbol【+】
4. 取出“*”: postfix_expre【1,2】,symbol【+,*】
5. 取出“(”: postfix_expre【1,2】,symbol【+,*,(】
6. 取出“3”: postfix_expre【1,2,3】,symbol【+,*,(】
7. 取出“-”: postfix_expre【1,2,3】,symbol【+,*,(,-】
8. 取出“4”: postfix_expre【1,2,3,4】,symbol【+,*,(,-】
9. 取出“)”: postfix_expre【1,2,3,4,-】,symbol【+,*】 //操作符堆栈symbol弹出操作符并加入到postfix_expre中,直到弹出左括号"("
10.取出“+”: postfix_expre【1,2,3,4,-,*,+】,symbol【+】 //加号优先级不大于【+,*】
11.取出“5”: postfix_expre【1,2,3,4,-,*,+,5】,symbol【+】
12.结束: postfix_expre【1,2,3,4,-,*,+,5,+】,symbol【】
*/
void get_postfix_expre(deque<char>& infix_expre,deque<char>& postfix_expre)
{
stack<char> symbol; //存放操作符
while(!infix_expre.empty())
{
char ch=infix_expre.front();
infix_expre.pop_front();
if(ch=='#')//如果是数字
postfix_expre.push_back(ch);
else if(ch=='(' )
symbol.push(ch);
else if(ch==')' )
{
char ch1=symbol.top();
symbol.pop();
while(ch1!='(' )
{
postfix_expre.push_back(ch1);
ch1=symbol.top();
symbol.pop();
}
}
else
{
if(symbol.empty())symbol.push(ch);
else
{
char ch2=symbol.top();
while(get_pri(ch)<=get_pri(ch2))
{
symbol.pop();
postfix_expre.push_back(ch2);
if(!symbol.empty())ch2=symbol.top();
else break;
}
symbol.push(ch);
}
}
}
while(!symbol.empty())
{
char ch3=symbol.top();
symbol.pop();
postfix_expre.push_back(ch3);
}
}
double calcu(double n1,double n2,char op)
{
double ans=0.0;
switch(op)
{
case '+':
ans=n1+n2;break;
case '-':
ans=n1-n2;break;
case '*':
ans=n1*n2;break;
case '/':
if(n2==0.0)exit(-3);
else ans=n1/n2;break;
default:
ans=0.0;break;
}
return ans;
}
//======================================================================================================
/*
后缀表达式到计算结果算法描述:
遍历储存后缀表达式的列表,将元素依次进栈,当遇到操作符时,连续出栈两个元素,进行运算,再将结果
进栈,最后栈内留下的元素就是计算结果
示例:
后缀表达式postfix_expre【1,2,3,4,-,*,+,5,+】,结果堆栈result【】
格式
输入-->:结果
[1,2,3,4]-->:result【1,2,3,4】
[-]-->:result【1,2,3-4】
[*]-->:result【1,2*(3-4)】
[+]-->:result【1+2*(3-4)】
[5]-->:result【1+2*(3-4),5】
[+]-->:result【1+2*(3-4)+5】
*/
double calculate(deque<char>& postfix_expre,deque<double>& data)
{
stack<double> result;
while(!postfix_expre.empty())
{
char ch=postfix_expre.front();
postfix_expre.pop_front();
if(ch=='#')
{
double da=data.front();
data.pop_front();
result.push(da);
}
else
{
double n1=result.top();
result.pop();
double n2=result.top();
result.pop();
double n3=calcu(n2,n1,ch);
result.push(n3);
}
}
return result.top();
}
int main()
{
char *ch="-2*3-6/(32.3+5*2*2-20.5)+3*(-3.3+2)";
deque<char> infix_expre; //中缀表达式
deque<char> postfix_expre; //后缀表达式
deque<double> data; //数据
get_infix_expre(ch,infix_expre,data); //由输入字符串获取中缀表达式
get_postfix_expre(infix_expre,postfix_expre); //获取后缀表达式
cout<<calculate(postfix_expre,data)<<endl;//由后缀表达式计算结果
system("pause");
return 0;
}
多项式乘法
最新推荐文章于 2022-04-06 16:56:02 发布