第六週—項目5 - 後綴表達式

問題及代碼:

/*
 *Copyright(c)2015,煙臺大學計算機與控制工程學院
 *All right reserved.
 *文件名稱:main.cpp
 *作者:程昂
 *完成日期;2015年10月9日
 *版本號;v1.0
 *
 *問題描述:利用sqstack.h中棧的基本運算,
 實現將一箇中綴表達式轉換爲對應的後綴表達式的算法。
 例如,輸入(56-20)/(4+2),輸出後綴表達式::56#20#-4#2#+/要求在數字後加#。
 *程序輸出: 輸出後綴表達式
*/

#include <stdio.h>
#include <stdlib.h>
#include "listack.h"
#define MaxOp 7

struct  //設定運算符優先級
{
    char ch;   //運算符
    int pri;   //優先級
}
lpri[]= {{'=',0},{'(',1},{'*',5},{'/',5},{'+',3},{'-',3},{')',6}},
rpri[]= {{'=',0},{'(',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};

int leftpri(char op)    //求左運算符op的優先級
{
    int i;
    for (i=0; i<MaxOp; i++)
        if (lpri[i].ch==op)
            return lpri[i].pri;
}

int rightpri(char op)  //求右運算符op的優先級
{
    int i;
    for (i=0; i<MaxOp; i++)
        if (rpri[i].ch==op)
            return rpri[i].pri;
}

bool InOp(char ch)       //判斷ch是否爲運算符
{
    if (ch=='(' || ch==')' || ch=='+' || ch=='-'
            || ch=='*' || ch=='/')
        return true;
    else
        return false;
}

int Precede(char op1,char op2)  //op1和op2運算符優先級的比較結果
{
    if (leftpri(op1)==rightpri(op2))
        return 0;
    else if (leftpri(op1)<rightpri(op2))
        return -1;
    else
        return 1;
}
void trans(char *exp,char postexp[])
//將算術表達式exp轉換成後綴表達式postexp
{
    LiStack *opstack;               //定義運算符棧
    int i=0;                //i作爲postexp的下標
    ElemType ch;
    InitStack(opstack);   //用初始化棧運算爲棧分配空間,務必要做
    Push(opstack, '=');
    while (*exp!='\0')      //exp表達式未掃描完時循環
    {
        if (!InOp(*exp))        //爲數字字符的情況
        {
            while (*exp>='0' && *exp<='9') //判定爲數字
            {
                postexp[i++]=*exp;
                exp++;
            }
            postexp[i++]='#';   //用#標識一個數值串結束
        }
        else    //爲運算符的情況
        {
            GetTop(opstack, ch);   //取得棧頂的運算符
            switch(Precede(ch ,*exp))
            {
            case -1:           //棧頂運算符的優先級低:進棧
                Push(opstack, *exp);
                exp++;     //繼續掃描其他字符
                break;
            case 0:        //只有括號滿足這種情況
                Pop(opstack, ch);      //將(退棧
                exp++;     //繼續掃描其他字符
                break;
            case 1:             //退棧並輸出到postexp中
                postexp[i++]=ch;
                Pop(opstack, ch);
                break;
            }
        }

    } //while (*exp!='\0')
    Pop(opstack, ch);
    while (ch!='=')
        //此時exp掃描完畢,退棧到'='爲止
    {
        postexp[i++]=ch;
        Pop(opstack, ch);
    }
    postexp[i]='\0';    //給postexp表達式添加結束標識
    DestroyStack(opstack);
}

int main()
{
    char exp[]="(56-20)/(4+2)"; //可將exp改爲鍵盤輸入
    char postexp[200];
    trans(exp,postexp);
    printf("中綴表達式:%s\n",exp);
    printf("後綴表達式:%s\n",postexp);
    return 0;
}



輸出及結果:



問題分析:

有個前提是判斷當前字符是數字還是運算符,首先看前面,數字的話進數組,運算符也進棧。依次進行下去,直到遇到下一個運算符,這時候要判斷運算符的優先級,將優先級大的那一項運算符出棧進入數組,

基於棧結構,將中綴表達式轉換爲後綴表達式的算法步驟是:

<code class="hljs mel has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">初始化運算符棧op;
將<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'='</span>進棧;
從<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">exp</span>讀取字符ch;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (ch!=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\0'</span>)
{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (ch不爲運算符)
     將後續的所有數字均依次存放到postexp中,並以字符<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'#'</span>標誌數值串結束;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> 
       <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">switch</span>(Precede(op棧頂運算符,ch))
       {
       <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'<'</span>:   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//棧頂運算符優先級低</span>
             將ch進棧;  從<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">exp</span>讀取下字符ch;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;
       <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'='</span>:   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//只有棧頂運算符爲'(',ch爲')'的情況</span>
             退棧; 從<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">exp</span>讀取下字符ch; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;
       <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'>'</span>:    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//棧頂運算符應先執行,所以出棧並存放到postexp中</span>
             退棧運算符並將其存放到postexp中; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;
      }
}</code>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章