怎樣用一個佇列和一個棧實現求一個表示式的值?
將中綴表示式轉化成字尾表示式儲存在佇列中,然後利用字尾表示式求表示式的值並輸出。
將中綴表示式轉化成字尾的思想:
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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【ZJOF】用來個棧來實現一個佇列佇列
- 資料結構 使用2個棧實現一個佇列資料結構佇列
- 用2個棧實現佇列佇列
- [每日一題] 第七題:用兩個棧實現佇列每日一題佇列
- 兩個棧實現佇列佇列
- 怎樣實現一個非阻塞的超時重試任務佇列佇列
- 兩個棧實現佇列操作佇列
- 題目9:用兩個棧實現佇列佇列
- 自己動手實現一個阻塞佇列佇列
- 面試題之【用兩個棧實現佇列】面試題佇列
- 你真的知道怎麼實現一個延遲佇列嗎?佇列
- excel表格中怎樣將一列的數值全部加上一個數值Excel
- 劍指offer-用兩個棧實現佇列-php佇列PHP
- 劍指offer | 09. 用兩個棧實現佇列佇列
- 用一個巨集實現求兩個數中的最大數
- C#實現一個萬物皆可排序的佇列C#排序佇列
- Python有 n 個物品和一個大小為 m 的揹包. 給定陣列 A 表示每個物品的大小和陣列 V 表示每個物品的價值.。。Python陣列
- java實現用一個變數表示多個屬性的狀態Java變數
- offer通過--7兩個棧實現佇列-2佇列
- offer通過--8兩個棧實現佇列-2佇列
- 用佇列實現棧佇列
- 用棧實現佇列佇列
- 如何寫一個任務佇列佇列
- 刷題系列 - 合併兩個順序佇列為一個新的佇列佇列
- 9. 題目:對佇列實現棧&用棧實現佇列佇列
- Day 10| 232.用棧實現佇列 、 225. 用佇列實現棧佇列
- React Hooks 起手式,實現一個「高顏值實用」的色彩設計工具ReactHook
- 如何用JavaScript手動實現一個棧JavaScript
- 一個數學表示式的計算
- 實現一個redis的分散式鎖Redis分散式
- 使用Node.js驅動Redis,實現一個訊息佇列!Node.jsRedis佇列
- 如何設計一個訊息佇列?佇列
- 一文讀懂一個URL請求的過程是怎樣的
- 使用Go語言實現一個超級mini的訊息佇列,我是這樣做的Go佇列
- 手把手教你用redis實現一個簡單的mq訊息佇列(java)RedisMQ佇列Java
- 劍指offer(java實現)第5題“用兩個棧實現佇列”-牛客網Java佇列
- 刷題系列 - 用遞迴和遍歷兩個方法反轉一個單鏈佇列遞迴佇列
- 實現一個 Redis 分散式鎖Redis分散式