(一道老坑爹的題)第三章棧作業題2-棧及其應用-計算機17級 7-1 表示式轉換 (25 分)
7-1 表示式轉換 (25 分)
算術表示式有字首表示法、中綴表示法和字尾表示法等形式。日常使用的算術表示式是採用中綴表示法,即二元運算子位於兩個運算數中間。請設計程式將中綴表示式轉換為字尾表示式。
輸入格式:
輸入在一行中給出不含空格的中綴表示式,可包含+
、-
、*
、\
以及左右括號()
,表示式不超過20個字元。
輸出格式:
在一行中輸出轉換後的字尾表示式,要求不同物件(運算數、運算子號)之間以空格分隔,但結尾不得有多餘空格。
輸入樣例:
2+3*(7-4)+8/4
輸出樣例:
2 3 7 4 - * + 8 4 / +
思路:mooc上的思路
從頭到尾讀取中綴表示式的每個物件,對不同物件按不同的情況處理。
1.運算數:直接輸出
2.左括號:壓入棧中
3.右括號:將棧頂的運算子彈出並輸出,直到遇到左括號(出棧,不輸出)
4.運算子:
若優先順序大於棧頂運算子時,則把它壓棧;
若優先順序小於等於棧頂運算子時,將棧頂運算子彈出並輸出;再比較新的棧頂運算子,直到該運算子大於棧頂運算子優先順序為止,然後將該運算子壓棧
5.若各物件處理完畢,則把堆疊中存留的運算子一併輸出
mooc思路補充:其實mooc上的思路完全沒問題,但具體實現的過程還會有很多坑,在這裡做一些補充
1.碰到數字直接輸出,但是這裡的數字可能是小數、負數(負號和數字是一起輸出的)或帶正號的數字;
小數的實現程式碼裡有解釋,仔細看應該ok
關於正負號與數字一起輸出有兩種特殊情況
第一種是正負號在第一位,例如:-1+2-1,此時負號要連著數字一起輸出,而如果第一位是正的則不用。
第二種是左括號連著正負號,例如:1+(-2-1)或者2+(+5)-1,此時左括號後的負號也要連著輸出,而左括號後的正號則不用
2.把演算法程式碼分為兩類,一類是數字類,一類是運算子類,其中關於正負號與數字一起輸出我們放在數字類,這屬於一種特殊情況的討論,而其餘的情況當做運算子處理即可。所以數字類包括整數,小數,以及那兩種特殊情況,而運算子類則包括左括號,右括號,以及加減乘數符號。這樣的話程式碼的邏輯會很清晰
if()//數字類
{
}
else//運算子類
{
}
3.關於運算子的優先順序,可以用map對映來表示,加減都設為1,乘除都設為2
4.一下這種程式碼要記得判空在前,順序很重要
這是網上找的測試樣例
話說這個題我之前是先實現堆疊再來做題的,畢竟資料結構學的就是這個嘛,但是用堆疊真的心累,卡了四天了,一直是段錯誤,實在是找不出來啊。。。所以這個題建議還是使用stl吧,方便太多了hh。。。當然我會把我那個全是段錯誤的題程式碼發出來,歡迎大佬們幫忙修改
先是stl寫的正確的程式碼
#include<bits/stdc++.h>
using namespace std;
stack<char> sta;
map<char,int> ma;//
int main()
{
ma['+'] = ma['-'] = 1;
ma['*'] = ma['/'] = 2;
string ss;
cin>>ss;
bool isfirst = true;
for(int i = 0;ss[i]; i++)
{
//判斷數字及特殊情況
//判斷ss為整數,為小數點,以及跟正負號與數字一起輸出有關的兩種特殊情況
if((isdigit(ss[i])) || (ss[i]=='.') || ((i==0||ss[i-1]=='(') && (ss[i]=='+' || ss[i]=='-')))
{
if(!isfirst)//用來控制格式
{
cout<<" ";
}
if(ss[i]!='+')//負數時直接輸出負號,正數則不用
{
cout<<ss[i];
}
while(ss[i+1]=='.'||isdigit(ss[i+1]))//如果是小數就繼續往後讀,之後自然會跳出這個迴圈
{
i++;
cout<<ss[i];
}
isfirst = false;
}
else//為運算子時
{
//cout<<" GG "<<i<<endl;
if(ss[i]=='(')//左括號:壓入棧中
{
sta.push(ss[i]);
}
else if(ss[i]==')')//右括號:將棧頂的運算子彈出並輸出,直到遇到左括號(出棧,不輸出)
{
while(!sta.empty() && sta.top()!='(')
{
cout<<" "<<sta.top();
sta.pop();
}
sta.pop();
}
else if(sta.empty() ||(ma[ss[i]] > ma[sta.top()]))//ss[i]的優先順序比棧頂元素的大
{
sta.push(ss[i]);
}
else
{
while(!sta.empty() && sta.top()!='(')//ss[i]的優先順序比棧頂元素的小或等
{
cout<<' '<<sta.top();
sta.pop();
}
sta.push(ss[i]);
}
}
}
while(!sta.empty())//最後把堆疊中存留的運算子一併輸出
{
cout<<" "<<sta.top();//注意此時不需要用flag控制格式,因為判斷數字那塊一定已經有了輸出
sta.pop();
}
return 0;
}
然後就是用實現棧寫的,答案是對的,但就是執行時他會卡一下,然後交上去一堆段錯誤。。。求大佬指點!!!
#include<cstdio>
#include<bits/stdc++.h>
#define STACK_INIT_SIZE 1000000
#define STACKINCREMENT 100000
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
//#define OVERFLOW -2
using namespace std;
typedef char SElemType,Status;
map<char,int> ma;//
typedef struct
{
SElemType *base;
SElemType *top;
int stacksize;
} SqStack;
Status InitStack(SqStack &S)
{
S.base = (SElemType*)malloc(sizeof(SElemType)*STACK_INIT_SIZE);
//if(!S.base)
//exit(OVERFLOW);
S.base = S.top;
S.stacksize += STACKINCREMENT;
return OK;
}
Status Push(SqStack &S,SElemType e)
{
if(S.top - S.base >= S.stacksize)
{
S.base = (SElemType*)realloc(S.base,(S.stacksize + STACKINCREMENT)*sizeof(SElemType));
//if(!S.base)
//exit(OVERFLOW);
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++ = e;
return OK;
}
Status Pop(SqStack &S)
{
if(S.top==S.base)
return ERROR;
return *--S.top;
//return OK;
}
SElemType GetTop(SqStack &S)
{
if(S.base==S.top)
return ERROR;
return *(S.top-1);
}
bool JudgeEmpty(SqStack &S)
{
if(S.top == S.base)
return true;
else
return false;
}
//勝利oid PrintStack(SqStack &S);
int main()
{
SqStack S;
ma['+'] = ma['-'] = 1;
ma['*'] = ma['/'] = 2;
InitStack(S);
string ss;
cin>>ss;
bool isfirst = true;
for(int i = 0; ss[i]; i++)
{
//判斷數字及特殊情況
//判斷ss為整數,為小數點,以及跟負號有關的兩種特殊情況
if((isdigit(ss[i])) || (ss[i]=='.') || ((i==0||ss[i-1]=='(') && (ss[i]=='+' || ss[i]=='-')))
{
if(!isfirst)
{
cout<<" ";
}
if(ss[i]!='+')//負數時直接輸出負號,正數則不用
{
cout<<ss[i];
}
while(ss[i+1]=='.'||isdigit(ss[i+1]))
{
i++;
cout<<ss[i];
}
isfirst = false;
}
else//為運算子時
{
if(ss[i]=='(')
{
Push(S,ss[i]);
}
else if(ss[i]==')')
{
while(!JudgeEmpty(S)&&GetTop(S)!='(')
{
cout<<" "<<GetTop(S);
Pop(S);
}
//if(!JudgeEmpty(S))
Pop(S);
}
else if(ma[ss[i]] <= ma[GetTop(S)])
{
while(!JudgeEmpty(S)&&GetTop(S)!='(')
{
cout<<" "<<GetTop(S);
Pop(S);
}
Push(S,ss[i]);
}
else if(JudgeEmpty(S)||(ma[ss[i]] > ma[GetTop(S)]) )//ss[i]的優先順序比棧頂元素的大
{
Push(S,ss[i]);
}
}
}
while(!JudgeEmpty(S))
{
cout<<" "<<GetTop(S);
Pop(S);
}
}
題目連結:https://pintia.cn/problem-sets/434/problems/5893
希望有大佬能幫我解決這個問題,畢竟這幾天一直是
。。。