1. 括号匹配算法
四则运算中合法的括号:
- 括号匹配成对出现
- 左括号必然先于右括号出现
使用栈对左右括号进行中缀到后缀前的检测:
for(int i=0; i<len; i++)
{
if(exp[i] 为左括号)
exp[i]入栈;
else if(exp[i] 为右括号)
{
if(栈顶元素为左括号)
栈顶元素弹出;
else
匹配错误;
}
}
2. 中缀转后缀
转换过程:
-当前元素e为数字:输出
-当前元素e为字符:
1. 与栈顶运算符进行优先级比较
2. 小于等于:将栈顶元素输出,转 1
3. 大于:将当前元素 e 入栈
-当前元素 e 为左括号:入栈
-当前元素 e 为右括号
1. 弹出栈顶元素并输出,直至栈顶元素为左括号
2. 将栈顶的左括号从栈中弹出
部分代码实现:
bool (QQueue<QString>& exp, QQueue<QString>& output) // exp是前缀表达式,output是转换后的后缀表达式
{
bool ret = match(exp); // 检查表达式括号是否正确
QStack<QString> stack;
output.clear();
while( ret && !exp.isEmpty() )
{
QString e = exp.dequeue();
if( isNumber(e) ) // 如果是数字直接进入后缀表达式队列
{
output.enqueue(e);
}
else if( isOperator(e) ) // 判断是否是操作符
{
while( !stack.isEmpty() && (priority(e) <= priority(stack.top())) ) // 比较操作符的优先级
{
output.enqueue(stack.pop());
}
stack.push(e);
}
else if( isLeft(e) ) // 如果是左括号入栈
{
stack.push(e);
}
else if( isRight(e) ) // 如果是右括号弹出栈顶元素直至为右括号,弹出的元素入后缀表达式队列
{
while( !stack.isEmpty() && !isLeft(stack.top()) )
{
output.enqueue(stack.pop());
}
if( !stack.isEmpty() )
{
stack.pop();
}
}
else // 其它则是错误情况,虽然这种情况似乎不可能发生,但是在C语言深度剖析中已经解释过,有些很特殊的情况可能会导致意外
{
ret = false;
}
}
while( !stack.isEmpty() ) // 将栈中所有的元素入后缀表达式队列
{
output.enqueue(stack.pop());
}
if( !ret )
{
output.clear();
}
return ret;
}
3. 总结
- 后缀表达式是计算复杂表达式的基础
- 中缀到后缀的转换是基于栈数据结构的
- 转换过程能够发现表达式中的语法错误