波兰式的各种表示及转化
中缀表达式转换为逆波兰表达式(后缀表达式):
首先需要分配2个栈,一个作为临时存储运算符的栈S1(含一个结束符号),一个作为输入逆波兰式的栈S2(空栈),S1栈可先放入优先级最低的运算符#,注意,中缀式应以此最低优先级的运算符结束。可指定其他字符,不一定非#不可。从中缀式的左端开始取字符,逐序进行如下步骤:
(1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入S2栈
(2)若取出的字符是运算符,则将该运算符与S1栈栈顶元素比较,如果该运算符优先级(不包括括号运算符)大于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,最后将该运算符送入S1栈。
(3)若取出的字符是“(”,则直接送入S1栈顶。
(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。
(5)重复上面的1~4步,直至处理完所有的输入字符
(6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送入S2栈。
完成以上步骤,S2栈便为逆波兰式输出结果。不过S2应做一下逆序处理。便可以按照逆波兰式的计算方法计算了!
摘自百度百科
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 typedef char SElemType_Char; 2 typedef struct { 3 SElemType_Char* base, * top; 4 int listsize; 5 }SqStack;//数据结构 6 7 Status InitSqStack(SqStack* S) { 8 (*S).base = (SElemType_Char*)malloc(STACK_INT_SIZE*sizeof(SElemType_Char)); 9 (*S).top = (*S).base; 10 (*S).listsize = STACK_INT_SIZE; 11 return OK; 12 }//初始化 13 14 Status Push_SqStack(SqStack* S, SElemType_Char e) { 15 *((*S).top++) = e; 16 return OK; 17 }//入栈 18 19 SElemType_Char Pop_SqStack(SqStack* S) { 20 return *--(*S).top; 21 }//出栈 22 23 void Convert(char* S,SqStack *T1,SqStack T2) { 24 char* t = S, *p; 25 Push_SqStack(&T2, '#'); 26 while (*t) { 27 switch (*t){ 28 case'+': 29 case'-': 30 if (*(T2.top - 1) == '#'|| *(T2.top - 1) == '(') 31 Push_SqStack(&T2, *t); 32 else { 33 do { 34 Push_SqStack(T1, Pop_SqStack(&T2)); 35 } while (*(T2.top - 1) != '#'); 36 Push_SqStack(&T2, *t); 37 } 38 break; 39 case'*': 40 case'/': 41 if (*(T2.top - 1) == '+' || *(T2.top - 1) == '-' || *(T2.top - 1) == '#' || *(T2.top - 1) == '(') 42 Push_SqStack(&T2, *t); 43 else { 44 do { 45 Push_SqStack(T1, Pop_SqStack(&T2)); 46 } while (*(T2.top - 1) == '+' || *(T2.top - 1) == '-' || *(T2.top - 1) == '#'); 47 Push_SqStack(&T2, *t); 48 } 49 break; 50 case')': 51 do { 52 Push_SqStack(T1, Pop_SqStack(&T2)); 53 } while (*(T2.top - 1) != '('); 54 Pop_SqStack(&T2); 55 break; 56 case'(': 57 Push_SqStack(&T2, *t); 58 break; 59 default: 60 Push_SqStack(T1, *t); 61 break; 62 } 63 t++; 64 } 65 while(T2.base!=T2.top-1) 66 Push_SqStack(T1, Pop_SqStack(&T2)); 67 p = (*T1).base; 68 while (p != (*T1).top) 69 printf("%c", *p++); 70 printf("\n"); 71 }//转化并输出
逆波兰式求解:
如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 char Calculate(SqStack T1,SqStack T2) { 2 char p, q; 3 while (T1.base != T1.top) 4 Push(&T2, Pop(&T1)); 5 while (T2.base != T2.top) { 6 if (*(T2.top - 1) >= '0' && *(T2.top - 1) <= '9') 7 Push(&T1, Pop(&T2)); 8 else { 9 if (*(T2.top - 1) == '+') 10 Push(&T1, (Pop(&T1) - '0') + (Pop(&T1) - '0')+'0'); 11 else if (*(T2.top - 1) == '-') { 12 p = Pop(&T1); 13 q = Pop(&T1); 14 Push(&T1, (q - '0') - (p - '0') + '0'); 15 } 16 else if (*(T2.top - 1) == '*') 17 Push(&T1, (Pop(&T1) - '0') * (Pop(&T1) - '0')+'0'); 18 else if (*(T2.top - 1) == '/') { 19 p = Pop(&T1); 20 q = Pop(&T1); 21 Push(&T1, (q - '0') / (p - '0') + '0'); 22 } 23 Pop(&T2); 24 } 25 } 26 return *T1.base; 27 }
中缀表达式转前缀表达式:
①从右到左扫描中缀表达式
②遇到数字压入S2
③遇到操作符,与S1的栈顶比较
a.如果S1为空,或者栈顶是 ),直接入栈S1
b.否则,如果符号优先级比栈顶高或者相等,直接入栈S1
c.否则,S1顶出栈,压入S2。然后继续回到步骤a比较。
④遇到括号的时候
a. ) :直接压入S1
b. ( :依次把S1弹出,压入S2,直到遇上 )。括号可以丢弃
⑤重复上述扫描步骤,直到扫描完成
⑥S1中如果还有元素,全部弹出压入S2
⑦S2依次弹出得到前缀表达式
---------------------
参考 https://blog.csdn.net/weixin_39731083/article/details/81667043
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Status Calculate(SqStack *S1,char *S3) { SqStack S2; InitSqStack(&S2); (*S1).top = (*S1).base; int i = strlen(S3) - 1; while (i >= 0) { switch (S3[i]){ case'+': case'-': case'*': case'/': do { if (S2.base == S2.top || *(S2.top - 1) == ')' || (S3[i] == '*' || S3[i] == '/')) { Push(&S2, S3[i]); break; } else if ((S3[i] == '+' || S3[i] == '-') && (*(S2.top - 1) == '+' || *(S2.top - 1) == '-')) { Push(&S2, S3[i]); break; } else Push(S1, Pop(&S2)); } while (1); break; case'(': while (*(S2.top - 1) != ')'&&S2.base!=S2.top) Push(S1, Pop(&S2)); if (S2.base != S2.top) Pop(&S2); break; case')': Push(&S2, S3[i]); break; default: Push(S1, S3[i]); break; } i--; } while (S2.base != S2.top) if (*(S2.top - 1) == ')') Pop(&S2); else Push(S1, Pop(&S2)); SElemType_Char* p; p = (*S1).top - 1; do { printf("%c", *p--); } while (p != (*S1).base); printf("%c\n", *p); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #define MAX_SIZE 100 2 3 typedef char SString[MAX_SIZE+1]; 4 typedef SString SqNode; 5 typedef struct { 6 SqNode* base; 7 int front, rear; 8 }SqStack;//数据格式 9 10 Status InitSqStack(SqStack* T) { 11 (*T).base = (SqNode*)malloc(MAX_SIZE*sizeof(SqNode)); 12 (*T).front = 0; 13 (*T).rear = 0; 14 return OK; 15 }//栈初始化 16 17 Status Push(SqStack_* T, SqNode e) { 18 int i; 19 (*T).base[++(*T).rear][0] = e[0]; 20 for (i = 1; i <= e[0]; i++) 21 (*T).base[(*T).rear][i] = e[i]; 22 return OK; 23 }//入栈 24 25 Status Pop(SqStack* T, SqNode* e) { 26 (*e)[0] = (*T).base[(*T).rear][0]; 27 for (int i = 1; i <= (*e)[0]; i++) 28 (*e)[i] = (*T).base[(*T).rear][i]; 29 (*T).rear--; 30 return OK; 31 }//出栈 32 33 Status Connect_4_13(SqNode* s, SqNode t1, SqNode t2) { 34 int i, j; 35 i = 1; j = 1; 36 while (i <= t1[0]) { 37 (*s)[i] = t1[i]; 38 i++; 39 } 40 while (j <= t2[0]) 41 (*s)[i++] = t2[j++]; 42 (*s)[0] = t1[0] + t2[0]; 43 return OK; 44 }//连接元素 45 46 Status OutPutSString(SString S) { 47 for (int i = 1; i <= S[0]; i++) 48 printf("%c", S[i]); 49 printf("\n"); 50 return OK; 51 }//输出元素 52 53 void Convert(char* s,SString* T) { 54 (*T)[0] = strlen(s); 55 SqStack S1; 56 InitSqStack(&S1); 57 SString e1, e2, e3; 58 int i = (*T)[0] - 1; 59 while (i>=0) { 60 e3[0] = 1; 61 e3[1] = s[i]; 62 switch (s[i]){ 63 case'+': 64 case'-': 65 case'*': 66 case'/': 67 Pop_4_13(&S1, &e1); 68 Pop_4_13(&S1, &e2); 69 Connect_4_13(&e1, e1, e2); 70 Connect_4_13(&e1, e1, e3); 71 Push_4_13(&S1, e1); 72 break; 73 default: 74 Push_4_13(&S1, e3); 75 break; 76 } 77 i--; 78 } 79 T = S1.base[1]; 80 OutPutSString(T); 81 }//转化