参考严蔚敏、吴伟民版《数据结构-C语言版》算法3-3(P52页)所介绍的——利用堆栈求解表达式值(一)
多项式后缀式的算法与程序源码
#+-*/%()(井号、加、减、乘、除、括号)字符堆栈 外的优先级函数定义:
char inStackWeight(char ch) {
switch (ch)
{
case '#':
return 0;
break;
case '(':case '(':
return 1;
break;
case ')':case ')':
return 6;
break;
case '+':case '-':
return 3;
break;
case '*':case '/':case '%':
return 5;
break;
default:
return 100;
break;
}
}
#+-*/%()(井号、加、减、乘、除、括号)字符堆栈 内的优先级函数:
char outStackWeight(char ch) {
switch (ch) {
case '#':
return 0;
break;
case '('://case '(':中文字符不是一个字节
return 6;
break;
case ')':
return 1;
break;
case '+':case '-':
return 2;
break;
case '*':case '/':case '%':
return 4;
break;
default:
return 100;
break;
}
}
单字节数字与符号判断函数定义:
char checkNumAndSymbol(char ch) {
switch (ch)
{
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9'://数字0-9
return 1;
break;
case '(':case ')':case '+':case '-':case '*':case '/':case '%'://运算符
return 2;
break;
default://其他
return 0;
break;
}
}
单字节字符的在堆栈的转置函数定义:
stack<char> reverseCharStack(stack<char> input) {
stack<char> result;
while (!input.empty()) {
result.push(input.top());
input.pop();
}
return result;
}
后缀式转换,重要函数的定义:
分为运算符和其他字符,通过出入堆栈将普通的表达式转成后缀式。
(eg:原表达式:a*b+(c-d/e)*f ,输出其后缀式为:ab*cde/-f*+ 。)
void change2SuffixForm(stack<char> &input) {//input输入:第一个字符在堆栈顶
stack<char> tempSk;
stack<char> symbolSk;
int inTp = 0;
symbolSk.push('#');//一定要加字符'#'作为参照
while (!input.empty()) {
inTp = input.top();
if (checkNumAndSymbol(inTp)==2) {//符号
if (outStackWeight(inTp)==1) {//如果是右括号')'
while (!symbolSk.empty())
{
if (outStackWeight(symbolSk.top()) == 6) {//如果是左括号'('
symbolSk.pop();//出栈
break;//退出循环
}
tempSk.push(symbolSk.top());
symbolSk.pop();
}
}else if (outStackWeight(inTp)<inStackWeight(symbolSk.top())) {//从符号堆栈中弹出到result
tempSk.push(symbolSk.top());
symbolSk.pop();
//把tempSk新弹出来的符号压入符号堆栈
symbolSk.push(inTp);
}
else {
symbolSk.push(inTp);
}
}
else {//数字
tempSk.push(inTp);
}
input.pop();
}
while (!symbolSk.empty()) {//将剩余的运算符出栈
if(symbolSk.top()!='#')
tempSk.push(symbolSk.top());
symbolSk.pop();
}
while (!tempSk.empty()) {
input.push(tempSk.top());
tempSk.pop();
}
}
最后是测试这个算法的主函数,为使得函数更具通用性,这里将输入和算法主体函数分离。
测试:
int main(void){
/*例:
输入:1*2+(3-4/5)*6
输出:12*345/-6*+
*/
stack<char> result;
stack<char> finalResult;
char ch;
while ((ch = getchar()) != '\n' && (ch != EOF)) {//通过回车结束表达式的输入
result.push(ch);
}
finalResult = reverseCharStack(result);//让最先输入的字符位于堆栈顶
change2SuffixForm(finalResult);
while (!finalResult.empty()) {
printf("%c",finalResult.top());
finalResult.pop();
}
system("pause");
return 0;
}
结果: