問題及代碼:
/*
*Copyright(c)2015,煙臺大學計算機與控制工程學院
*All right reserved.
*文件名稱:main.cpp
*作者:程昂
*完成日期;2015年10月9日
*版本號;v1.0
*
*問題描述:利用sqstack.h中棧的基本運算,
實現將一箇中綴表達式轉換爲對應的後綴表達式的算法。
例如,輸入(56-20)/(4+2),輸出後綴表達式::56#20#-4#2#+/要求在數字後加#。
*程序輸出: 輸出後綴表達式
*/
#include <stdio.h>
#include <stdlib.h>
#include "listack.h"
#define MaxOp 7
struct //設定運算符優先級
{
char ch; //運算符
int pri; //優先級
}
lpri[]= {{'=',0},{'(',1},{'*',5},{'/',5},{'+',3},{'-',3},{')',6}},
rpri[]= {{'=',0},{'(',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};
int leftpri(char op) //求左運算符op的優先級
{
int i;
for (i=0; i<MaxOp; i++)
if (lpri[i].ch==op)
return lpri[i].pri;
}
int rightpri(char op) //求右運算符op的優先級
{
int i;
for (i=0; i<MaxOp; i++)
if (rpri[i].ch==op)
return rpri[i].pri;
}
bool InOp(char ch) //判斷ch是否爲運算符
{
if (ch=='(' || ch==')' || ch=='+' || ch=='-'
|| ch=='*' || ch=='/')
return true;
else
return false;
}
int Precede(char op1,char op2) //op1和op2運算符優先級的比較結果
{
if (leftpri(op1)==rightpri(op2))
return 0;
else if (leftpri(op1)<rightpri(op2))
return -1;
else
return 1;
}
void trans(char *exp,char postexp[])
//將算術表達式exp轉換成後綴表達式postexp
{
LiStack *opstack; //定義運算符棧
int i=0; //i作爲postexp的下標
ElemType ch;
InitStack(opstack); //用初始化棧運算爲棧分配空間,務必要做
Push(opstack, '=');
while (*exp!='\0') //exp表達式未掃描完時循環
{
if (!InOp(*exp)) //爲數字字符的情況
{
while (*exp>='0' && *exp<='9') //判定爲數字
{
postexp[i++]=*exp;
exp++;
}
postexp[i++]='#'; //用#標識一個數值串結束
}
else //爲運算符的情況
{
GetTop(opstack, ch); //取得棧頂的運算符
switch(Precede(ch ,*exp))
{
case -1: //棧頂運算符的優先級低:進棧
Push(opstack, *exp);
exp++; //繼續掃描其他字符
break;
case 0: //只有括號滿足這種情況
Pop(opstack, ch); //將(退棧
exp++; //繼續掃描其他字符
break;
case 1: //退棧並輸出到postexp中
postexp[i++]=ch;
Pop(opstack, ch);
break;
}
}
} //while (*exp!='\0')
Pop(opstack, ch);
while (ch!='=')
//此時exp掃描完畢,退棧到'='爲止
{
postexp[i++]=ch;
Pop(opstack, ch);
}
postexp[i]='\0'; //給postexp表達式添加結束標識
DestroyStack(opstack);
}
int main()
{
char exp[]="(56-20)/(4+2)"; //可將exp改爲鍵盤輸入
char postexp[200];
trans(exp,postexp);
printf("中綴表達式:%s\n",exp);
printf("後綴表達式:%s\n",postexp);
return 0;
}
輸出及結果:
問題分析:
有個前提是判斷當前字符是數字還是運算符,首先看前面,數字的話進數組,運算符也進棧。依次進行下去,直到遇到下一個運算符,這時候要判斷運算符的優先級,將優先級大的那一項運算符出棧進入數組,
基於棧結構,將中綴表達式轉換爲後綴表達式的算法步驟是:
<code class="hljs mel has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">初始化運算符棧op; 將<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'='</span>進棧; 從<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">exp</span>讀取字符ch; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (ch!=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\0'</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (ch不爲運算符) 將後續的所有數字均依次存放到postexp中,並以字符<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'#'</span>標誌數值串結束; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">switch</span>(Precede(op棧頂運算符,ch)) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'<'</span>: <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//棧頂運算符優先級低</span> 將ch進棧; 從<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">exp</span>讀取下字符ch; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'='</span>: <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//只有棧頂運算符爲'(',ch爲')'的情況</span> 退棧; 從<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">exp</span>讀取下字符ch; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'>'</span>: <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//棧頂運算符應先執行,所以出棧並存放到postexp中</span> 退棧運算符並將其存放到postexp中; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>; } }</code>