1. 程式人生 > >演算法訓練 表示式計算 ——藍橋杯

演算法訓練 表示式計算 ——藍橋杯

問題描述

  輸入一個只包含加減乖除和括號的合法表示式,求表示式的值。其中除表示整除。

輸入格式

  輸入一行,包含一個表示式。

輸出格式

  輸出這個表示式的值。

樣例輸入

1-2+3*(4-5)

樣例輸出

-4

資料規模和約定

  表示式長度不超過100,表示式運算合法且運算過程都在int內進行。

這個題的思路就是先把中綴表示式轉化為字尾表示式,然後用字尾表示式計算出式子的值

1.將中綴表示式轉換為字尾表示式的方法:
(1) 初始化兩個棧:運算子棧S1和儲存中間結果的棧S2;
(2) 從左至右掃描中綴表示式;
(3) 遇到運算元時,將其壓入S2,這裡由於運算數可能大於10,所以如果數字後面一個符號是運算子,則將‘#’入S2棧充當分割線;


(4) 遇到運算子時有三種情況:
(4-1) 三種情況下直接入S1棧①S1為空②運算子為‘(’③運算子優先順序比S1棧頂運算子的高
(4-2)如果右括號“)”,則依次彈出S1棧頂的運算子,並壓入S2,直到遇到左括號為止,此時將這一對括號丟棄
(4-3) 若運算子優先順序小於或等於S1棧頂運算子的優先順序,則依次彈出S1棧頂元素,直到運算子的優先順序大於S1棧頂運算子優先順序
(6) 重複步驟(2)至(5),直到表示式的最右邊;
(7) 將S1中剩餘的運算子依次彈出並壓入S2;
(8) 依次彈出S2中的元素並輸出,結果的逆序即為中綴表示式對應的字尾表示式。

運算子優先順序:(乘=除)>(加=減)>(左括號=右括號)。

例:將 1 + ( ( 23 + 34 ) * 5 ) - 6轉化為中綴表示式

掃描到的元素

S2(棧底->棧頂)

S1 (棧底->棧頂)

說明

1

1

數字,直接入棧,下一個元素是運算子#入棧

+

1

+

S1為空,運算子直接入棧

(

1

+ (

左括號,直接入棧

(

1

+ ( (

左括號,直接入棧

2

1 # 2

+ ( (

數字,直接入棧下一個元素不是運算子

3

1 # 2 3 #

+ ( (

數字,直接入棧,下一個元素是運算子#入棧

+

1 # 2 3 #

+ ( ( +

+優先順序大於S1棧頂運算子,直接入棧.

3

1 # 2 3 # 3

+ ( ( +

數字,直接入棧,下一個元素不是運算子

4

1 # 2 3 # 3 4 #

+ ( ( +

數字,直接入棧,下一個元素是運算子#入棧

)

1 # 2 3 # 3 4 # +

+ (

右括號,彈出S1運算子直至遇到左括號,將彈出的元素壓入S2中,丟棄一對括號

*

1 # 2 3 # 3 4 # +

+ ( *

*優先順序大於S1棧頂運算子,直接入棧.

5

1 # 2 3 # 3 4 # + 5 #

+ ( *

數字,直接入棧,下一個元素是運算子#入棧

)

1 # 2 3 # 3 4 # + 5 # *

+

右括號,彈出S1運算子直至遇到左括號,將彈出的元素壓入S2中,丟棄一對括號

-

1 # 2 3 # 3 4 # + 5 # * +

 -

-+優先順序相同,因此彈出+,再壓入-

6

1 # 2 3 # 3 4 # + 5 # * + 6 #

 -

數字,直接入棧,下一個元素是運算子#入棧

到達最右端

1 # 2 3 # 3 4 # + 5 # * + 6 # - 

S1中剩餘的運算子彈出並壓入S2

所以計算結果為:1 # 2 3 # 3 4 # + 5 # * + 6 # -

2.字尾表示式計算方法:

(1)定義一個int棧S3,定義一個整形陣列num用來儲存大於10的數字便於計算,從左至右掃描表示式。

(2)遇到數字時:

(2-1)若數字後面一個元素不是#(數字後面只可能是#或數字)則將數字字元轉化為數字存在num[ ]陣列中;

(2-2)若數字後面一個元素是#,將num陣列中儲存的數字算出來並壓入S3棧中。

(3)遇到運算子時,彈出S3棧頂的兩個數,用運算子對它們做相應的計算(次頂元素 op 棧頂元素),並將結果入棧;重複上述過程直到表示式最右端,最後運算得出的值即為表示式的結果。

例如字尾表示式“1 # 2 3 # 3 4 # + 5 # * + 6 # -”:

掃描到的元素

S3(棧底->棧頂)

num[ ](從左到右下標從0遞增)

說明

1

1

1

數字,下一個元素為#故將num中算出來壓入S3中

#

1

1

#,跳過,(下一次賦值從num[0]開始)

2

1

2

數字,下一個元素不為#故將元素轉化為數字存入num中

3

1 23

2 3

數字,下一個元素為#故將num中算出來壓入S3中

#

1 23

2 3

#,跳過

3

1 23

3 3

數字,下一個元素不為#故將元素轉化為數字存入num中,注意從num[0]開始

4

1 23 34

3 4

數字,下一個元素為#故將num中算出來壓入S3中

#

1 23 34

3 4

#,跳過

+

1 57

3 4

+,彈出S3棧頂兩元素,進行加法計算後壓入棧中

5

1 57 5

5 4

數字,下一個元素為#故將num中算出來壓入S3中

#

1 57 5

5 4

#,跳過

*

1 285

5 4

*,彈出S3棧頂兩元素,進行乘法計算後壓入棧中

+

286

5 4

+,彈出S3棧頂兩元素,進行加法計算後壓入棧中

6

286 6

6 4

數字,下一個元素為#故將num中算出來壓入S3中

#

286 6

6 4

#,跳過

-

280

6 4

-,彈出S3棧頂兩元素,進行減法計算後壓入棧中。

所以最後計算的結果為280

#include<iostream>    
#include<cstring>    
#include<stack>    
#include<algorithm> 
#include<cmath>    
using namespace std;    
    
stack<char> s1,s2;    
stack<int> s3;    
char ch[150]={0};//用來存表示式    
int num[11];//用來暫時存數字    
          
int priority(char ch)//用於比較字元優先順序    
{    
    if(ch==')'||ch=='(') return 1;    
    if(ch=='+'||ch=='-') return 2;    
    if(ch=='*'||ch=='/') return 3;         
}    
         
int Scal(int x,int y,char ope)//兩個數的運算    
{    
    if(ope=='+') return x+y;    
    if(ope=='-') return x-y;    
    if(ope=='*') return x*y;    
    if(ope=='/'&&y!=0) return x/y;    
}    
    
void Transform(int n)//將中綴表示式轉化為字尾表示式    
{    
    int k=0;    
    for(int i=0;i<n;i++)       
        if(ch[i]>='0'&&ch[i]<='9')//當是數字的情況       
            if(i+1<n&&(ch[i+1]<'0'||ch[i+1]>'9')||i==n-1)//當是最後一個數字,或下一個元素是運算子    
            {    
                s2.push(ch[i]);    
                s2.push('#');    
            }    
            else    
                s2.push(ch[i]);     
        else      
            if(s1.empty()||ch[i]=='('||priority(ch[i])>priority(s1.top()))//當是運算子,有3種情況直接入棧    
                s1.push(ch[i]);                 
            else if(ch[i]==')')//當是右括號的情況    
            {    
                while(s1.top()!='(')    
                {    
                    s2.push(s1.top());      
                    s1.pop();    
                }    
                s1.pop();    
            }    
            else//當運算子優先順序小於或等於S1棧頂運算子的優先順序  
            {    
                while(!s1.empty()&&priority(ch[i])<=priority(s1.top())&&s1.top()!='(')//這裡還要注意兩個界限    
                {    
                    s2.push(s1.top());    
                    s1.pop();               
                }    
                s1.push(ch[i]);     
            }       
    while(!s1.empty())//當表示式結束    
    {    
        s2.push(s1.top());    
        s1.pop();           
    }    
    while(!s2.empty()) //將棧內元素放回S2中    
    {    
        ch[k++]=s2.top();    
        s2.pop();       
    }    
    reverse(ch,ch+k);//將ch[]反向    
    ch[k]=0;    
}    
    
int Cal(int n)//字尾表示式計算    
{    
    int x,y,tmp=0,k=0;    
    for(int i=0;i<n;i++)       
        if(ch[i]=='#')//是#直接跳過    
            continue;    
        else if(ch[i]=='+'||ch[i]=='-'||ch[i]=='*'||ch[i]=='/')//是運算子彈出棧頂兩元素計算後放回棧    
        {    
            x=s3.top();    
            s3.pop();    
            y=s3.top();    
            s3.pop();    
            x=Scal(y,x,ch[i]);    
            s3.push(x);    
        }    
        else//是數字字元       
            if(ch[i+1]=='#')//下一個元素是#    
            {    
                num[k++]=ch[i]-'0';    
                for(int i=0;i<k;i++)    
                    tmp+=(num[i]*(int)pow(10,k-i-1));    
                s3.push(tmp);    
                tmp=0;    
                k=0;                    
            }    
            else//下一個元素不是#       
                num[k++]=ch[i]-'0';                  
    return s3.top();    
}    
    
int main()    
{    
    gets(ch);    
    Transform(strlen(ch));    
    cout<<Cal(strlen(ch))<<endl;    
    return 0;    
}    

相關推薦

演算法訓練 表示式計算 ——藍橋

問題描述   輸入一個只包含加減乖除和括號的合法表示式,求表示式的值。其中除表示整除。 輸入格式   輸入一行,包含一個表示式。 輸出格式   輸出這個表示式的值。 樣例輸入 1-2+3*(4-5) 樣例輸出 -4 資料規模和約定   表示式長度不超過1

演算法-藍橋-演算法訓練 表示式計算 (JAVA)

1 引言什麼題。。。2 題目問題描述  輸入一個只包含加減乖除和括號的合法表示式,求表示式的值。其中除表示整除。輸入格式  輸入一行,包含一個表示式。輸出格式  輸出這個表示式的值。樣例輸入1-2+3*(4-5)樣例輸出-4資料規模和約定  表示式長度不超過100,表示式運算

藍橋--演算法訓練 表示式計算

問題描述   輸入一個只包含加減乖除和括號的合法表示式,求表示式的值。其中除表示整除。 輸入格式   輸入一行,包含一個表示式。 輸出格式   輸出這個表示式的值。 樣例輸入

藍橋 演算法訓練 表示式計算

演算法訓練 表示式計算 時間限制:1.0s 記憶體限制:256.0MB 提交此題 問題描述   輸入一個只包含加減乖除和括號的合法表示式,求表示式的值。其中除表示整除。 輸入格式   輸入一行,包含一個表示式。 輸出格式   輸出這個表示式的

藍橋演算法訓練 表示式計算

本文參考部落格http://www.cnblogs.com/z-y-p/p/3676945.html 問題描述   輸入一個只包含加減乖除和括號的合法表示式,求表示式的值。其中除表示整除。 輸入格式   輸入一行,包含一個表示式。 輸出格式   輸出這個表示

演算法訓練 傳紙條 藍橋

問題描述   小淵和小軒是好朋友也是同班同學,他們在一起總有談不完的話題。一次素質拓展活動中,班上同學安排做成一個m行n列的矩陣,而小淵和小軒被安排在矩陣對角線的兩端,因此,他們就無法直接交談了。幸運的是,他們可以通過傳紙條來進行交流。紙條要經由許多同學傳到對方手裡,小淵坐

演算法提高 日期計算 藍橋 詳解

演算法提高 日期計算   時間限制:1.0s   記憶體限制:256.0MB 問題描述   已知2011年11月11日是星期五,問YYYY年MM月DD日是星期幾?注意考慮閏年的情況。

Java實現表示式計算 藍橋

題目在這裡http://lx.lanqiao.cn/problem.page?gpid=T419 輸入一個只包含加減乖除和括號的合法表示式,求表示式的值。 表示式計算雖然看起來挺簡單的,但是編碼起來也不是想象中的那麼容易。雖說上課的時候,有講過逆波蘭表示式,但是還沒動手實現

警察智力訓練--藍橋歷年java真題(java遞迴實現eval演算法

匪警請撥110,即使手機欠費也可撥通!    為了保障社會秩序,保護人民群眾生命財產安全,警察叔叔需要與罪犯鬥智鬥勇,因而需要經常性地進行體力訓練和智力訓練!    某批警察叔叔正在進行智力訓練:    1 23 4 5 6 7 8 9 = 110;    請看上邊

演算法訓練 薪水計算

問題描述   編寫一個程式,計算員工的週薪。薪水的計算是以小時為單位,如果在一週的時間內,員工工作的時間不超過40 個小時,那麼他/她的總收入等於工作時間乘以每小時的薪水。如果員工工作的時間在40 到50 個小時之間,那麼對於前40 個小時,仍按常規方法計算;而對於剩餘的超

ALGO-62 演算法訓練 平方計算

  演算法訓練 平方計算   時間限制:1.0s   記憶體限制:512.0MB      問題描述   輸入正整數a, m,輸出a^2%m,其中^表示乘方,即a^2表示a的平方,%表示取餘。 輸入格式

演算法提高 素數求和 藍橋 (篩選法)

/*  演算法提高 素數求和  問題描述  輸入一個自然數n,求小於等於n的素數之和樣例輸入2樣例輸出2資料規模和約定  測試樣例保證 2 <= n <= 2,000,000*/#include <stdio.h>#include <stdlib

演算法訓練 斜率計算

  輸入兩個點的座標,即p1 = (x1, y1)和p2=(x2, y2),求過這兩個點的直線的斜率。如果斜率為無窮大輸出“INF”。 樣例輸入 1 2 2 4 樣例輸出 2 樣例輸入 1

演算法練習——表示式計算

問題描述   輸入一個只包含加減乖除和括號的合法表示式,求表示式的值。其中除表示整除。 輸入格式   輸入一行,包含一個表示式。 輸出格式   輸出這個表示式的值。 樣例輸入 1-2+3*(4-5) 樣例輸出 -4 資料規模和約定 表示式長度不超過100,表示式運算合法且運

藍橋_演算法訓練_表示式計算

  之前在學習棧的時候老師講過這個問題   思路就是:     1.將表示式(中綴式)轉化成字尾式;     2.進行字尾式的計算。    思路看起來很簡單,但是實際在敲程式碼的時候還是要注意很多問題。

藍橋 演算法訓練 ALGO-92 字首表示式 字元操作 數學知識

演算法訓練 字首表示式 時間限制:1.0s 記憶體限制:512.0MB 提交此題 問題描述   編寫一個程式,以字串方式輸入一個字首表示式,然後計算它的值。輸入格式為:“運算子 物件1 物件2”,其中,運算子為“+”(加法)、“-”(減法)、“*”(乘法)或“/”(除法),運算物件為

藍橋練習系統演算法訓練——字首表示式運算

問題描述   編寫一個程式,以字串方式輸入一個字首表示式,然後計算它的值。輸入格式為:“運算子 物件1 物件2”,其中,運算子為“+”(加法)、“-”(減法)、“*”(乘法)或“/”(除法),運算物件

藍橋 演算法訓練 字母圖形

問題描述 利用字母可以組成一些美麗的圖形,下面給出了一個例子: ABCDEFG BABCDEF CBABCDE DCBABCD EDCBABC 這是一個5行7列的圖形,請找出這個圖形的規律,並輸出一個n行m列的圖形。 輸入格式 輸入一行

藍橋 演算法訓練 區間k大數查詢

明明是一個水題卻wrong answer了很多遍。。 還是因為對最基礎的氣泡排序概念不清。蠢死算了。 這下終於搞清楚了。 問題描述 給定一個序列,每次詢問序列中第l個數到第r個數中第K大的數是哪個。 輸入格式 第一行包含一個數

藍橋 ALGO-47 演算法訓練 蜜蜂飛舞

問題描述“兩隻小蜜蜂呀,飛在花叢中呀……” 話說這天天上飛舞著兩隻蜜蜂,它們在跳一種奇怪的舞蹈。用一個空間直角座標系來描述這個世界,那麼這兩隻蜜蜂初始座標分別為(x1,y1,z1),(x2,y2,z2)  。在接下來它們將進行n次飛行,第i次飛行兩隻蜜蜂分別按照各自的速度向量飛行ti個單位時間。