[基础算法]通过后缀表达式实现表达式的计算
生活随笔
收集整理的這篇文章主要介紹了
[基础算法]通过后缀表达式实现表达式的计算
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
要求說明:
(1)從鍵盤接收算術表達式,以“#”表示接收結束;
(2)輸出算術表達式的值;
(3)操作數僅限于非負整數,操作符只能是+、-、*、/、^、(、)
(4)可以判斷表達式的合法性(如括號的匹配)
寫作業時遇到的一道題目,覺得比較麻煩,估計以后會有人遇到相同的問題,就寫了篇博客記錄下來。
主要思路:
(1)先將表達式轉化成后綴表達式
(2)逐個讀取后綴表達式,計算結果
轉化成后綴表達式:
(1)設立操作符棧。
(2)設表達式的結束符為“#”,預設操作符棧的棧底為“#”。
(3)若當前字符是操作數,則直接發送給后綴式。
(4)若當前字符為操作符且優先級大于棧頂操作符,則人棧,否則退出棧頂操作符發送給后綴式。
(5)若當前字符是結束符,則自棧頂至棧底依次將棧中所有操作符發送給后綴式。
(6)“(”對它之前后的操作符起隔離作用,則若當前操作符為“(”時人棧。
(7)“)”可視為自相應左括號開始表達式的結束符,則從棧頂起,依次退出棧頂操作
符發送給后綴式直至棧頂字符為“("止。“(”不發送到后綴式。
轉化成后綴表達式函數代碼:
/*SeqStack *L操作符棧,char *str1讀取的表達式,char *str2返回的后綴表達式*/ void Conversion(SeqStack *S,char *str1,char *str2) {int i=0;char *p=str1,e;//預設操作符棧的棧底為“#”Push(S,'#');while (*p!='\0'){//若當前字符不是操作符是操作數,則直接發送給后綴式。if (!Isoperator(*p)){str2[i++]=*p;}else{if (*p=='(')Push(S,*p);else if (*p==')'){while(GetTop(S)!='('){Pop(S,&e);str2[i++]=e;}Pop(S,&e); /*pop掉前括號*/}else if (*p=='#'){while (!IsEmpty(S)){Pop(S,&e);str2[i++]=e;}}else if (Compare(*p,GetTop(S))){Push(S,*p);}else if (!Compare(*p,GetTop(S))){Pop(S,&e);str2[i++]=e;continue; /*continue應該要加*/}}p++;}str2[i-1]='\0'; /*#號也存進去了,所以用'\0'覆蓋掉*/ }完整計算表達式代碼:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <conio.h> #define TRUE 1 #define FALSE 0 #define Stack_Size 50char ops[8]= {'+','-','*','/','(',')','^','#'}; /*運算符數組*/ int priority[8] = {1,1,2,2,0,0,3,-1};typedef struct {char elem[Stack_Size];int top; } SeqStack; /*運算符棧的定義*/typedef struct {int elem[Stack_Size];int top; } nSeqStack; /* 運算數棧的定義*/void InitStack(SeqStack *S) /*初始化運算符棧*/ {S->top =-1; }void InitStackn(nSeqStack *S) /*初始化運算數棧*/ {S->top =-1; }int IsEmpty(SeqStack *S) /*判斷棧S為空棧時返回值為真,反之為假*/ {return(S->top==-1?TRUE:FALSE); }int IsEmptyn(nSeqStack *S) /*判斷棧S為空棧時返回值為真,反之為假*/ {return(S->top==-1?TRUE:FALSE); }/*判棧滿*/ int IsFull(SeqStack *S) /*判斷棧S為滿棧時返回值為真,反之為假*/ {return(S->top==Stack_Size-1?TRUE:FALSE); }int IsFulln(nSeqStack *S) /*判斷棧S為滿棧時返回值為真,反之為假*/ {return(S->top==Stack_Size-1?TRUE:FALSE); }int Push(SeqStack *S, char x) /*運算符棧入棧函數*/ {if (S->top==Stack_Size-1){printf("Stack is full!\n");return FALSE;}else{S->top++;S->elem[S->top]=x;return TRUE;} }int Pushn(nSeqStack *S, int x) /*運算數棧入棧函數*/ {if (S->top==Stack_Size-1){printf("Stack is full!\n");return FALSE;}else{S->top++;S->elem[S->top]=x;return TRUE;} }int Pop(SeqStack *S, char *x) /*運算符棧出棧函數*/ {if (S->top==-1){printf("運算符棧空!\n");return FALSE;}else{*x=S->elem[S->top];S->top--;return TRUE;} }int Popn(nSeqStack *S, int *x) /*運算數棧出棧函數*/ {if (S->top==-1){printf("運算數棧空!\n");return FALSE;}else{*x=S->elem[S->top];S->top--;return TRUE;} }char GetTop(SeqStack *S) /*運算符棧取棧頂元素函數*/ {if (S->top ==-1){printf("運算符棧為空!\n");return FALSE;}else{return (S->elem[S->top]);} }int GetTopn(nSeqStack *S) /*運算數棧取棧頂元素函數*/ {if (S->top ==-1){printf("運算符棧為空!\n");return FALSE;}else{return (S->elem[S->top]);} }int Isoperator(char ch) /*判斷輸入字符是否為運算符函數,是返回TRUE,不是返回FALSE*/ {int i;for (i=0; i<8; i++){if(ch==ops[i])return TRUE;}return FALSE; }int Compare(char c1,char c2) {int m,n;/*賦值c1對應的n*/if (c1=='+' || c1=='-')m=1;else if (c1=='*' || c1=='/')m=2;else if (c1=='(' || c1==')')m=0;else if (c1=='^')m=3;else if (c1=='#')m=-1;/*賦值c2對應的n*/if (c2=='+' || c2=='-')n=1;else if (c2=='*' || c2=='/')n=2;else if (c2=='(' || c2==')')n=0;else if (c2=='^')n=3;else if (c2=='#')n=-1;return m>n; }/*SeqStack *L操作符棧,char *str1讀取的表達式,char *str2返回的后綴表達式*/ void Conversion(SeqStack *S,char *str1,char *str2) {int i=0;char *p=str1,e;//預設操作符棧的棧底為“#”Push(S,'#');while (*p!='\0'){//若當前字符不是操作符是操作數,則直接發送給后綴式。if (!Isoperator(*p)){str2[i++]=*p;}else{if (*p=='(')Push(S,*p);else if (*p==')'){while(GetTop(S)!='('){Pop(S,&e);str2[i++]=e;}Pop(S,&e); /*pop掉前括號*/}else if (*p=='#'){while (!IsEmpty(S)){Pop(S,&e);str2[i++]=e;}}else if (Compare(*p,GetTop(S))){Push(S,*p);}else if (!Compare(*p,GetTop(S))){Pop(S,&e);str2[i++]=e;continue; /*continue應該要加*/}}p++;}str2[i-1]='\0'; /*#號也存進去了,所以用'\0'覆蓋掉*/ }int Calc(char *str) {nSeqStack *n,nn;n=&nn;int i;int x,y,result;char *p=str;InitStackn(n);while (*p!='\0'){if (!Isoperator(*p)){Pushn(n,*p-'0');}else{Popn(n,&x);Popn(n,&y);switch (*p){case '+':result=y+x;break;case '-':result=y-x;break;case '*':result=y*x;break;case '/':result=y/x; /*假設都能整除*/break;case '^':result=y;for (i=1;i<x;i++){result=result*y;}break;default:printf("error\n");break;}Pushn(n,result);}p++;}return result; }int main() {/**整體步驟*(1)表達式轉化成后綴表達式*(2)表達式逐個讀取進行計算*/char str1[100],str2[100];scanf("%s",str1);SeqStack *s,ss;s=&ss;InitStack(s);Conversion(s,str1,str2);printf("后綴表達式:%s\n",str2);int result = Calc(str2);printf("表達式結果:%d\n",result);return 0; }附:
利用后綴表達式求解,只需要從左向右依次掃描表達式,
(1)遇到操作數人棧,
(2)遇到操作符.則做出棧兩次,獲得兩個操作數,
后出棧的操作數為第一個操作對象,對它們進行計算,
計算結果作為下次運算的操作數入棧。
重復上述操作,直到后綴表達式讀取結束,既可完成表達式的計算。
總結
以上是生活随笔為你收集整理的[基础算法]通过后缀表达式实现表达式的计算的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Web前端_项目实践01_萌娃摄影网页(
- 下一篇: [数据结构考前必看]中缀表达式转化成后缀