1. 程式人生 > >(一道老坑爹的題)第三章棧作業題2-棧及其應用-計算機17級 7-1 表示式轉換 (25 分)

(一道老坑爹的題)第三章棧作業題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

希望有大佬能幫我解決這個問題,畢竟這幾天一直是

。。。