使用棧實現表示式求值,運用棧計算

cpp小白發表於2020-09-26

使用棧實現表示式求值

題目要求

	讀取一個多項式,使用棧進行多項式求值,並輸出結果。

##思路

	1.使用兩個棧,nums用於儲存運算元,ops用於儲存操作符
	2.從左往右掃描,遇到運算元入棧nums
	3.遇到操作符時,如果優先順序低於或等於棧頂操作符優先順序,則從nums彈出兩個元素進行計算,並壓入nums,
	  繼續與棧頂操作符的比較優先順序
	4.如果遇到操作符高於棧頂操作符優先順序,則直接入棧ops
	5.遇到左括號,直接入棧ops,遇到右括號,則直接出棧並計算,直到遇到左括號
#include<bits/stdc++.h>//萬能標頭檔案,沒有的話需要手動下載
typedef int datatype;
#define maxsize 64
//定義順序棧結構
struct seqstack
{
	datatype data[maxsize];
	int top;
};
//定義基本函式
seqstack* CREATES()
{
	seqstack* p;
	p = (seqstack*)malloc(sizeof(seqstack));
	p->top = -1;
	return p;
}

seqstack* SETNULL(seqstack* S)
{
	S->top = -1;
}

int EMPTY(seqstack* S)
{
	if (S->top >= 0)
		return false;
	else
		return true;
}

seqstack* PUSH(seqstack* s, datatype x)
{
	if (s->top == maxsize - 1)
	{
		printf("overflow");
		return NULL;
	}
	else
	{
		s->top++;
		s->data[s->top] = x;
	}
	return s;
}

datatype POP(seqstack* s)
{
	if (EMPTY(s))
	{
		printf("underflow");
		return NULL;
	}
	else
	{
		s ->top--;
		return s->data[s->top + 1];
	}
}

datatype TOP(seqstack* s)
{
	if (EMPTY(s))
	{
		printf("underflow");
		return NULL;
	}
	else
	{
		return s->data[s->top];
	}
}
//記錄運算子號優先順序
static char pre[128] = { 0 };


//定義優先順序
void setpre()
{
    pre['+'] = 4;
    pre['-'] = 4;
    pre['*'] = 3;
    pre['/'] = 3;
    pre['('] = 1;
    pre[')'] = 1;
}

//建立字串接收字串型資料
string gets()
{
	string s;
	cin >> s ;
	return s;
}

//比較兩個符號的優先順序,如果op2高於op1則返回fu值,相等為0,低於為z值
int precompare(char op1, char op2)
{
    return pre[op2] -pre[ op1];
}

//計算操作,只負責計算,將所得資料壓入num中;
int active(seqstack* num, seqstack* ops)
{
    int a, b, r=0,op;
        op=POP(ops);
        if (op == '(')
            op = POP(ops);
        b = POP(num);
        a = POP(num);
        printf("get b from stack %d\n", b);
        printf("get a from stack %d\n", a);
        printf("get op from stack %c\n", op);
        switch (op)
        {
        case '+':
        {
            printf("push %d into stack\n", a + b);
            r=a+b;
            PUSH(num, r);
            break;
        }
        case '-':
        {
            printf("push %d into stack\n", a - b);
            r=a-b;
            PUSH(num, r);
            break;
        }
        case '*':
        {
            printf("push %d into stack\n", a * b);
             r = a * b;
             PUSH(num, r);
            break;
        }
        case '/':
        {
            printf("push %d into stack\n", a / b);
            r=a/b;
            PUSH(num, r);
            break;
        }
        }
       
        return r;
}

//整體操作,進行運算,得出結果
int addition(string str)
{
    cout << str << endl;
    int i=0, j, k, flag, temp;
    //建立兩個棧,nums裝填數字,ops裝填操作符
    seqstack* nums, * ops;
    nums = CREATES();
    ops = CREATES();
    while (str[i] != '#')//遍歷多項式
    {
        cout << str[i]<<"   ";
        if (str[i] >= '0' && str[i] <= '9')//判斷是否為數字
        {
            if (flag == 1)//判斷前一個字元是否為數字,如果是,彈出乘10加下一位
            {
                temp = POP(nums);
            }
            else
                temp = 0;
            temp = temp * 10 + str[i] - '0';
            flag = 1;
            PUSH(nums, temp);
        }
        //判斷是否為操作符,如果是則進行判斷和計算
        else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/')
        {
            flag = 0;
            if (ops->top<0)//判斷運算元棧是否為空棧,是則直接插入,不是則判斷是否需要運算
            {
                PUSH(ops, str[i]);
            }
            else
            {
                if (precompare(TOP(ops),str[i])>=0)//如果新輸入的符號優先順序低於之前的,進行計算
                {
                    if (TOP(ops) == '(')
                        PUSH(ops, str[i]);
                    else
                    {
                       active(nums, ops);
                        PUSH(ops, str[i]);
                    }
                }
                else
                {
                     
                    PUSH(ops, str[i]);
                    
                }
            }
        }
        else if (str[i] == '(')//左括號直接壓入
        {
            flag = 0;
            PUSH(ops, str[i]);
        }
        else if (str[i] == ')')//右括號對左側進行彈出計算
        {
            flag = 0;
            while (TOP(ops) !='(')//遍歷到左括號結束
            {
                if (TOP(ops) == '(')
                {
                    POP(ops);
                    break;
                }
                active(nums, ops);
                printf("%c\n", TOP(ops));
            }
        }
        i++;
    }
    while (!EMPTY(nums) && !EMPTY(ops))//判斷是否計算完全,即運算元棧為空
    {
        active(nums, ops);
    }
    temp = POP(nums);
    printf("%d\n", temp);
    return 0;
}

int main()
{
    string s;
    setpre();
    //freopen("D:\\學習X\\資料結構\\基礎操作實現\\text.in", "r", stdin);
    s = gets();
    addition(s);
    return 0;
}

相關文章