中缀表达式:运算符都在运算数之间的表达式,也就是我们日常见到的表达式,包含括号。例如:(1+2)*5
后缀表达式:别称逆波兰式,指的是严格从左向右按照运算符出现的顺序进行计算,不包含括号,运算符都放在运算对象的后面的。例如:1 2 + 5 * 就是一个后缀表达式,是由前面中缀表达式的例子转换的。
为什么要转换成后缀表达式?中缀表达式不行吗?
那是因为对于一个中缀表达式 5+8/2 ,我们人可以轻易知道各运算的次序得到答案 9 ,可是计算机不能,计算机很笨,所以需要转换成后缀表达式 5 8 2 / +,这样计算机就能在不考虑各符号优先级的情况下,也得出答案 9(计算机从左向右遍历,将5、8、2入栈,遇到 / ,将8、2出栈,将 8/2 的结果入栈,此时栈中有 5 4 ,遇到 +,将5、4出栈,将 5+4 的结果入栈,遍历完了,栈中有 9,这就是答案。)
思路:先从左向右遍历整个中缀表达式
1、如果是运算数:直接输出到后缀表达式
2、遇到左括号 ( :压入栈中,把左括号当做优先级最低的符号
3、遇到右括号 ) :意味着括号中的运算结束了,将运算符一个一个弹出栈顶并且输出到后缀表达式,直到遇到左括号,但是左括号不加入到后缀表达式
4、对于运算符 + - * /:
1.如果优先级大于栈顶的运算符或者栈为空时,入栈
2.否则,即优先级小于等于栈顶的运算符,就将栈顶依次弹出到后缀表达式中去,直到满足入栈条件。
( 此时是优先级最低的符号
遍历完中缀表达式后,可能栈中还存有运算符,依次弹出直至栈空。
转换过程分析(以(3+5)*3-2/1为样例,结果是3 5 + 3 * 2 1 / -):
1.遍历到(,入栈
后缀表达式为:
栈中元素:(
2.遍历到3,输出到后缀表达式
后缀表达式为:3
栈中元素:(
3.遍历到+(优先级1),大于栈顶元素(的优先级,入栈
后缀表达式为:3
栈中元素:(+
4.遍历到5,输出到后缀表达式
后缀表达式为:3 5
栈中元素:(+
5.遍历到),一直出栈输出到后缀表达式,直到遇到(,但是(不加入后缀表达式
后缀表达式为:3 5 +
栈中元素:
6.遍历到*,栈为空,入栈
后缀表达式为:3 5 +
栈中元素:*
7.遍历到3,输出到后缀表达式
后缀表达式为:3 5 + 3
栈中元素:*
8.遍历到-,小于等于*的优先级,*出栈输出到后缀表达式,-入栈
后缀表达式为:3 5 + 3 *
栈中元素:-
9.遍历到2,输出到后缀表达式
后缀表达式为:3 5 + 3 * 2
栈中元素:-
10.遍历到/,/的优先级大于-,入栈
后缀表达式为:3 5 + 3 * 2
栈中元素:-/
11.遍历到1,输出到后缀表达式
后缀表达式为:3 5 + 3 * 2 1
栈中元素:-/
12.遍历完了,可是栈未空,出栈直至栈空
后缀表达式为:3 5 + 3 * 2 1 / -
栈中元素:
至此结束 。
int priority(char ch) //返回优先级-优先级越高值越大
{
if (ch == '(')
{
return 0;
}
else if (ch == '+' || ch == '-')
{
return 1;
}
else // * /
{
return 2;
}
}
void trans(string arr1, string &arr2)
{
Stack stack;
initStack(stack);
DateElem e = ' '; //用于传出栈中元素
for (int i = 0; i < arr1.size(); i++) //每次arr2加入元素后,都加一个空格以分割
{
if (arr1[i] == ' ') //跳过空格
{
continue;
}
if(arr1[i] >= '0' && arr1[i] <= '9') //情况1
{
while (arr1[i] >= '0' && arr1[i] <= '9')
{
arr2.push_back(arr1[i]);
i++;
}
arr2.push_back(' ');
i--; //因为当不是数字时,i也++了,i等下循环中还要++,所以得--
}
else if (arr1[i] == '(' ) //情况2
{
pushStack(stack, arr1[i]);
}
else if (arr1[i] == ')') //情况3
{
while (!IsEmpty(stack) && getTop(stack)!='(')
{
popStack(stack, e);
arr2.push_back(e);
arr2.push_back(' ');
}
if(getTop(stack) == '(')
popStack(stack,e); //将 '(' 弹出栈
}
else //情况4
{
while (!IsEmpty(stack) && priority(getTop(stack) ) >=priority( arr1[i] )) //栈不为空 并且 栈顶元素优先级大于等于遍历的字符
{
popStack(stack, e);
arr2.push_back(e);
arr2.push_back(' ');
}
pushStack(stack, arr1[i]); //循环结束,就满足入栈条件,栈为空 或者 优先级小于栈顶元素
}
}
while (!IsEmpty(stack)) //输出栈中剩余的元素
{
popStack(stack, e);
arr2.push_back(e);
arr2.push_back(' ');
}
return;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
using namespace std;
//栈的数据结构定义
#define MAX_SIZE 120
typedef char DateElem;
typedef struct _Stack
{
DateElem* top;
DateElem* base;
}Stack;
//初始化栈
bool initStack(Stack& s)
{
s.base = new DateElem[MAX_SIZE];
if (!s.base) return false; //空间分配失败
s.top = s.base; //空栈
return true;
}
//入栈
bool pushStack(Stack& s, DateElem e)
{
if (!s.base || (s.top - s.base) >= MAX_SIZE) return false; //栈没建立 或者 栈满了
*(s.top++) = e;
return true;
}
//出栈
bool popStack(Stack& s, DateElem& e)
{
if (!s.base || s.base == s.top) return false;
e = *(--s.top); //先将栈顶元素赋值给e,栈顶指针再移动,因为栈顶指针都是指向栈顶元素的后一个位置
return true;
}
//获取栈顶元素
DateElem getTop(Stack& s)
{
if (s.top > s.base) //栈不为空
{
return *(s.top - 1);
}
else
{
cout << "栈为空" << endl;
return 1;
}
}
//判断栈是否为空
bool IsEmpty(Stack& s)
{
if (s.base == s.top)
{
return true;
}
else
{
return false;
}
}
//获取栈中元素的个数
int getLength(Stack& s)
{
return (int)(s.top - s.base);
}
//销毁栈
void destoryStack(Stack& s)
{
//与初始化栈一一对应
if (s.base != NULL) //有效
{
delete s.base;
s.base = s.top = NULL;
}
}
int priority(char ch) //返回优先级-优先级越高值越大
{
if (ch == '(')
{
return 0;
}
else if (ch == '+' || ch == '-')
{
return 1;
}
else // * /
{
return 2;
}
}
void trans(string arr1, string &arr2)
{
Stack stack;
initStack(stack);
DateElem e = ' '; //用于传出栈中元素
for (int i = 0; i < arr1.size(); i++) //每次arr2加入元素后,都加一个空格以分割
{
if (arr1[i] == ' ') //跳过空格
{
continue;
}
if(arr1[i] >= '0' && arr1[i] <= '9') //情况1
{
while (arr1[i] >= '0' && arr1[i] <= '9')
{
arr2.push_back(arr1[i]);
i++;
}
arr2.push_back(' ');
i--; //因为当不是数字时,i也++了,i等下循环中还要++,所以得--
}
else if (arr1[i] == '(' ) //情况2
{
pushStack(stack, arr1[i]);
}
else if (arr1[i] == ')') //情况3
{
while (!IsEmpty(stack) && getTop(stack)!='(')
{
popStack(stack, e);
arr2.push_back(e);
arr2.push_back(' ');
}
if(getTop(stack) == '(')
popStack(stack,e); //将 '(' 弹出栈
}
else //情况4
{
while (!IsEmpty(stack) && priority(getTop(stack) ) >=priority( arr1[i] )) //栈不为空 并且 栈顶元素优先级大于等于遍历的字符
{
popStack(stack, e);
arr2.push_back(e);
arr2.push_back(' ');
}
pushStack(stack, arr1[i]); //循环结束,就满足入栈条件,栈为空 或者 优先级小于栈顶元素
}
}
while (!IsEmpty(stack)) //输出栈中剩余的元素
{
popStack(stack, e);
arr2.push_back(e);
arr2.push_back(' ');
}
return;
}
int main(void)
{
Stack stack;
initStack(stack);
string arr1 = "";
string arr2= "";
cout << "请输入中缀表达式:"; //((1+2)*3)-(6-5)
getline(cin, arr1);
trans(arr1, arr2);
cout << "转为后缀表达式为:"; //1 2 + 3 * 6 5 - -
cout << arr2 << endl;
return 0;
}
其中包括了栈的代码,你也可以使用库中的栈。