怎樣用一個佇列和一個棧實現求一個表示式的值?

程式碼女民工發表於2021-09-23

將中綴表示式轉化成字尾表示式儲存在佇列中,然後利用字尾表示式求表示式的值並輸出。

將中綴表示式轉化成字尾的思想:

1、建立一空佇列,用來存放字尾表示式,建立並初始化運算子棧OPTR,將表示式起始符“#”壓入OPTR棧。

2、依次讀入表示式中每個字元ch,迴圈執行(3)至(5),直至求出整個表示式轉換完畢。

3、取出OPTR的棧頂元素,當OPTR的棧頂元素和當前讀入的字元ch均為“#”時,整個中綴表示式轉換完畢。

4、若ch不是運算子,則進隊,讀入下一字元ch。

5、若ch是運算子,則根據OPTR的棧頂元素和ch的優先權比較結果,做不同的處理。

① 若是小於,則ch壓入OPTR棧,讀入下一字元ch。

② 若是大於,則彈出OPTR棧頂的運算子,進隊。

③ 若是等於,則OPTR的棧頂元素是“(”且ch是“)”,這時彈出OPTR棧頂的“(”,相當於去掉括號,然後讀入下一字元ch。


#include<stdio.h> 

#include<malloc.h>

#include<stdlib.h>

#include<string.h>

#define OVERFLOW -2

#define MAXSIZE 100

#define OK 1 

#define ERROR 0

#define TRUE 1

#define FALSE 0

#include<iostream>

using namespace std;


typedef int Status;

typedef char SElemType;



typedef struct

{

    SElemType *base;

    int front;

    int rear;

}SqQueue;


Status InitQueue(SqQueue &Q)  //初始化

{


    Q.base=new SElemType[MAXSIZE];

    if(!Q.base) exit(OVERFLOW);

    Q.front=Q.rear=0;

    return OK;

}

Status EnQueue (SqQueue &Q,SElemType e)  //入隊

{

    if((Q.rear+1)%MAXSIZE==Q.front)

        return ERROR;

    Q.base[Q.rear]=e;

    Q.rear=(Q.rear+1)%MAXSIZE;

    return OK;


}

Status DeQueue(SqQueue &Q,SElemType &e)  //出隊

{

    if(Q.front==Q.rear)

        return ERROR;

    e=Q.base[Q.front];

    Q.front=(Q.front+1)%MAXSIZE;

    return OK;

}

SElemType GetHead(SqQueue Q)//取隊頭元素

{

    if(Q.front!=Q.rear)

        return Q.base[Q.front];

}



//--------順序棧的儲存結構------

typedef struct 

{

    SElemType *base;    //棧底指標 

    SElemType *top;    //棧頂指標 

    int stacksize;     //佔可用的最大容量 

}SqStack; 



Status InitStack (SqStack &S)

{//構造一個空棧 

    S.base=new SElemType[MAXSIZE];   //為順序棧動態分配一個最大容量為MAXSIZE的陣列空間 

    if (!S.base) exit(OVERFLOW);    //動態分配失敗

    S.top=S.base;     //top初始為base,空棧 

    S.stacksize=MAXSIZE;   //stacksize置為棧的最大容量MAXSIZE 

    return OK;

    

}


Status Push(SqStack &S,SElemType e) 

{//插入元素e為新的棧頂元素

    if(S.top-S.base==S.stacksize)   return ERROR;   //棧滿 

    *S.top++=e;    //元素e壓入棧頂,棧頂指標加1 

    return OK;

    

}


Status Pop(SqStack &S,SElemType &e)

{//刪除s的棧頂元素,用e返回其    

    if (S.top==S.base)  return ERROR;  //棧頂 

    e=*--S.top;   // 棧頂指標減1,將棧頂元素為e 

    return OK;

    


SElemType GetTop(SqStack S) 

{//返回S的棧頂元素,不修改棧頂指標、

    if(S.top!=S.base)   //棧非空

        return *(S.top-1);   //返回棧頂元素的值,棧頂指標不變     

}



Status In(SElemType c)

{

    switch(c)          //判斷讀入的字元是哪一種運算子, 

    {

        case '+':

            return TRUE;

            break; 

        case '-':

            return TRUE;

            break;

        case '*':

            return TRUE;

            break;

        case '/':

            return TRUE;

            break;

        case '(':

            return TRUE;

            break;

        case ')':

            return TRUE;

            break;

        case '#':

            return TRUE;

            break;

        default:

            return FALSE;

            

    }

}


SElemType Precede(SElemType t1,SElemType t2)

{

    SElemType f;       

    switch(t2)     //判斷運算子棧的棧頂元素和讀入的運算子之間誰的優先順序更高,並返回結果 

    {

        case '+':

            if (t1=='('||t1=='#')

                f='<';

            else

                f='>';

            break;

            

        case '-':

            if (t1=='('||t1=='#')

                f='<';

            else

                f='>';

            break;

            

        case '*':

            if (t1=='+'||t1=='-'||t1=='('||t1=='#')

                f='<';

            else

                f='>';

            break;

            

        case '/':

            if (t1=='+'||t1=='-'||t1=='('||t1=='#')

                f='<';

            else

                f='>';

            break;

                

        case '(':

            if (t1=='+'||t1=='-'||t1=='('||t1=='#'||t1=='*'||t1=='/')

                f='<';

            break;

            

        case ')':

            if (t1=='+'||t1=='-'||t1=='*'||t1=='/'||t1==')')

                f='>';

            else if (t1=='(')

                f='=';

            break;

            

        case '#':

            if (t1=='#')

                f='=';

            else

                f='>';

            break;    

        default:

            cout<<"輸入超出範圍。。。";

        

    }

    return f;

}



SElemType Operate(SElemType a,SElemType theta,SElemType b)

{    

    SElemType c;

    a=a-'0';      //因為a,b均為字元型,所以轉化成int型 

    b=b-'0';

    switch(theta)

    {

        case '+':

            c=a+b+'0';break;        //再將計算的結果轉化為字元型 

        case '-':

            c=a-b+'0';break;

        case '*':

            c=a*b+'0';break;

        case '/':

            c=a/b+'0';break;        

    }

    return c;   //返回計算結果 

}


char EvaluateExpression()

{//算數表示式求值的算符優先演算法,設OPTR和 OPND分別為運算子棧和運算元棧

    SqStack OPTR;

    SqQueue OPND;

    char ch,theta,a,b,c,x,w;

    InitQueue(OPND);  //初始化OPND佇列

    InitStack(OPTR);  //初始化OPTR棧 

    Push(OPTR,'#');   //將表示式起始符“#”OPTR棧 

    cin>>ch;

    while (ch!='#'||GetTop(OPTR)!='#')    //表示式沒有掃描完畢或者OPTR的棧頂元素不為“#” 

    {

        if (!In(ch))     //判斷ch是不是運算子,不是則入OPND隊 

            {

                EnQueue(OPND,ch);

             cin>>ch;

            }

        else

            switch(Precede(GetTop(OPTR),ch))   // 比較OPTR的棧頂元素和ch的優先順序 

            {

                case '<':

                    Push(OPTR,ch);        //當前字元ch壓入OPTR棧 ,讀入下一個字元ch 

                    cin>>ch;

                    break;

                case '>':

                    Pop(OPTR,theta);    //彈出OPTR棧頂的運算子 

                    b=GetHead(OPND);        //彈出OPND佇列的運算數, 

                    a=GetHead(OPND);        //彈出OPND佇列的運算數,

                    EnQueue(OPND,Operate(a,theta,b));   //將運算結果入OPND佇列 

                    break;

                case '=':               //OPTR的棧頂元素是“(”且ch是“)”

                    Pop(OPTR,x);        //彈出OPTR棧頂的"(",

                    cin>>ch;            //讀入下一個字元ch 

                    break;

                

            }

    }

    return GetHead(OPND);              //OPND佇列元素即為表示式求值結果 

    

}

int main()

{

    char w;

    cout<<"請輸入算數表示式,並以#結束\n";

    w=EvaluateExpression();    //將運算結果賦值給w 

    w=w-48;         //將字元轉換成數字 

    printf("The result of expression is %d\n",w); 

                   

}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70007056/viewspace-2793245/,如需轉載,請註明出處,否則將追究法律責任。

相關文章