演算法訓練 表示式計算 ——藍橋杯
問題描述
輸入一個只包含加減乖除和括號的合法表示式,求表示式的值。其中除表示整除。
輸入格式
輸入一行,包含一個表示式。
輸出格式
輸出這個表示式的值。
樣例輸入
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個單位時間。