中缀表达式

学习算法,开始想到用栈了,但是没有解决优先级的问题。上网一查,原来中缀表达式更适合计算机阅读,转换成中缀表达式后,只需把转换好的数据压栈,遇到运算符就取出两个操作数的顺序第一个取出的放到运算符右侧运算之后压栈直到结束,取出栈顶数据就是结果。
编写时自己实现的函数

int count = -1;  
char pop(){  
    return stack[count--];  
}  
  
char top(){  
    return stack[count];  
}  
  
void push(char t){  
    stack[++count]=t;  
}  

别人比较好的代码

//字符串转换为数字  
x = 0;    
while('0' <= s2[i]&&s2[i] <= '9')    
 {    
    x = x*10+s2[i] - '0';    
    i++;    
 }    
 if(s2[i] == '.')    
 {    
    double k = 10.0;    
     y = 0;    
     i++;    
     while('0' <= s2[i]&&s2[i] <= '9')    
     {    
        y += ((s2[i]-'0')/k);    
         i++;    
         k *= 10;    
     }    
    x += y;    
}    

原帖:http://www.nowamagic.NET/librarys/veda/detail/2307
我们把平时所用的标准四则运算表达式,即“9+(3-1)3+10/2"叫做中缀表达式。因为所有的运算符号都在两数字的中间,现在我们的问题就是中缀到后缀的转化。
中缀表达式“9+(3-1)
3+10/2”转化为后缀表达式“9 3 1-3*+ 10 2/+”

规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

下面我们来具体看看这个过程。

  1. 初始化一空栈,用来对符号进出栈使用。
  2. 第一个字符是数字9,输出9,后面是符号“+”,进
  3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。
  4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。


  5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -
  6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“”,因为此时的栈顶符号为“+”号,优先级低于“”,因此不输出,进栈。
  7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。
  8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。


  9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2
  10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+


从刚才的推导中你会发现,要想让计算机具有处理我们通常的标准(中缀)表达式的能力,最重要的就是两步:

将中缀表达式转化为后缀表达式(栈用来进出运算的符号)。
将后缀表达式进行运算得出结果(栈用来进出运算的数字)。

整个过程,都充分利用了找的后进先出特性来处理,理解好它其实也就理解好了栈这个数据结构

/* 
*    这里主要是逆波兰式的实现,使用两个stack 这里用字符串来模拟一个stack,第一步,将中缀表达式转变为后缀表达式 
*    第二步,然后再使用一个stack,计算后缀表达式的结果,这一步很容易出错,考虑到浮点数的问题。 
*/  
#include <iostream>  
#include <string>  
#include <stack>  
#include <iomanip>  
  
using namespace std;  
  
int cmp(char ch)     // 运算符优先级   
{  
    switch(ch)  
    {  
        case '+':  
        case '-': return 1;  
        case '*':  
        case '/': return 2;  
        default : return 0;  
    }  
}  
void change(string &s1, string &s2)       // 中缀表达式转变后缀表达式   
{  
    stack <char > s;  
    s.push('#');  
    int i = 0;  
    while(i < s1.length()-1)  
    {  
        if(s1[i] == '(')  
        {  
            s.push(s1[i++]);  
        }  
        else if(s1[i] == ')')  
        {  
            while(s.top() != '(')  
            {  
                s2 += s.top();  
                s2 += ' ';  
                s.pop();  
            }  
            s.pop();  
            i++;  
        }  
        else if(s1[i] == '+'||s1[i] == '-'||s1[i] == '*'||s1[i] == '/')  
        {  
            while(cmp(s.top()) >= cmp(s1[i]))  
            {  
                s2 += s.top();  
                s2 += ' ';  
                s.pop();  
            }  
            s.push(s1[i]);  
            i++;  
        }  
        else  
        {  
            while('0' <= s1[i]&&s1[i] <= '9'||s1[i] == '.')  
            {  
                s2 += s1[i++];  
            }  
            s2 += ' ';  
        }  
    }  
    while(s.top() != '#')  
    {  
        s2 += s.top();  
        s2 += ' ';  
        s.pop();  
    }  
}  
  
double value(string s2)         // 计算后缀表达式,得到其结果。   
{  
    stack < double> s;  
    double x,y;  
    int i = 0;  
    while(i < s2.length())  
    {  
        if(s2[i] == ' ')  
        {  
            i++;  
            continue;  
        }  
        switch(s2[i])  
        {  
            case '+': x = s.top(); s.pop(); x += s.top(); s.pop(); i++; break;  
            case '-': x = s.top(); s.pop(); x =s.top()-x; s.pop(); i++; break;  
            case '*': x = s.top(); s.pop(); x *= s.top(); s.pop(); i++; break;  
            case '/': x = s.top(); s.pop(); x = s.top()/x; s.pop(); i++; break;  
            default :  
            {  
                x = 0;  
                while('0' <= s2[i]&&s2[i] <= '9')  
                {  
                    x = x*10+s2[i] - '0';  
                    i++;  
                }  
                if(s2[i] == '.')  
                {  
                    double k = 10.0;  
                    y = 0;  
                    i++;  
                    while('0' <= s2[i]&&s2[i] <= '9')  
                    {  
                        y += ((s2[i]-'0')/k);  
                        i++;  
                        k *= 10;  
                    }  
                    x += y;  
                }  
            }  
        }  
        s.push(x);  
    }  
    return s.top();  
}  
int main(int argc, char const *argv[])  
{  
    int n;  
    string s1,s2;  
    cin>>n;  
    while(n--)  
    {  
        cin>>s1;  
        s2 = "";  
        change(s1,s2);  
        cout<<fixed<<setprecision(2)<<value(s2)<<endl;  
    }  
    return 0;  
}  
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容