1.关于中缀表达式和后缀表达式
我们常见的表达式是中缀表达式形式,即二元运算符在两个操作数的中间,如“3+4*5”
而后缀表达式则是运算符位于两个操作数之后。 如“3+4*5”转化为后缀表达式为“3 4 5 * +”
2.基本思路
1.我们首先将中缀表达式转化为后缀表达式
2.对后缀表达式求值
3.1.1 数据结构:
源表达式使用字符串的形式存储,为了简便起见,这里操作数限制为1个数字,运算符限制为+,-,*,/,(和)总共6个符号
目标表达式(后缀表达式)用链表形式存储。链表的每个节点为2个字段,第1个字段表示类型,可能的取值有2种,表示是操作符还是数字。 第2个字段是一个union,存储操作符或者操作数。
除此之外,在转换过程中需要使用一个栈来存储中间过程用到的运算符。
3.1.2 算法
遍历中缀表达式中的数字和符号。
对于数字直接,将这个数字字符转化为一个整数,插入到链表尾部。
对于左括号,进栈。
对于运算符,将其与栈顶符号的优先级比较,若栈顶符号优先级低,此符号进栈。否则将栈顶符号弹出,并插入到链表尾部,之后将此运算符进栈。
我们定义左括号的优先级最低,值为0,+和-优先级为1,*和/优先级最高,值为2.
对于右括号,将栈顶符号弹出并插入到链表,直到遇到左括号为止,左括号不插入到链表.
最后,将栈中所有符号弹出并插入到链表。
3.2 对后缀表达式求值。
3.2.1 数据结构,此过程仅作用于链表,输入和输出都是链表
3.2.2 算法
当链表长度大于2时,反复应用下列过程
从链表头开始遍历,直到找到一个包含运算符的节点。
我们常见的表达式是中缀表达式形式,即二元运算符在两个操作数的中间,如“3+4*5”
而后缀表达式则是运算符位于两个操作数之后。 如“3+4*5”转化为后缀表达式为“3 4 5 * +”
2.基本思路
1.我们首先将中缀表达式转化为后缀表达式
2.对后缀表达式求值
3.具体实现
3.1 将中缀表达式转化为后缀表达式3.1.1 数据结构:
源表达式使用字符串的形式存储,为了简便起见,这里操作数限制为1个数字,运算符限制为+,-,*,/,(和)总共6个符号
目标表达式(后缀表达式)用链表形式存储。链表的每个节点为2个字段,第1个字段表示类型,可能的取值有2种,表示是操作符还是数字。 第2个字段是一个union,存储操作符或者操作数。
除此之外,在转换过程中需要使用一个栈来存储中间过程用到的运算符。
3.1.2 算法
遍历中缀表达式中的数字和符号。
对于数字直接,将这个数字字符转化为一个整数,插入到链表尾部。
对于左括号,进栈。
对于运算符,将其与栈顶符号的优先级比较,若栈顶符号优先级低,此符号进栈。否则将栈顶符号弹出,并插入到链表尾部,之后将此运算符进栈。
我们定义左括号的优先级最低,值为0,+和-优先级为1,*和/优先级最高,值为2.
对于右括号,将栈顶符号弹出并插入到链表,直到遇到左括号为止,左括号不插入到链表.
最后,将栈中所有符号弹出并插入到链表。
3.2 对后缀表达式求值。
3.2.1 数据结构,此过程仅作用于链表,输入和输出都是链表
3.2.2 算法
当链表长度大于2时,反复应用下列过程
从链表头开始遍历,直到找到一个包含运算符的节点。
将这个节点以及这个节点之前的2个节点做运算,如3个节点为"3,5,*", 则计算"3*5",结果为15,存入第三个节点,然后将运算符节点前面的2个节点删除,这个操作的实质是将3个节点合并为1个节点。
以下为源代码
#include <stack>
#include <list>
#include <iostream>
using namespace std;
enum e_type { is_num,is_op};
typedef struct _lsItem
{
e_type type;
union
{
int n;
char op;
}u;
}LS_ITEM;
bool is_number(char c)
{
return c>='0' && c<='9';
}
int get_priority(char c)
{
if (c=='*' || c=='/')
return 2;
else if ( c=='+' || c=='-')
return 1;
else
return 0;
}
void operator_handle( stack<char> &stack, char c, list<LS_ITEM> &ls )
{
char top;
LS_ITEM item;
while (1)
{
if ( stack.empty() )
{ stack.push(c); break; }
top= stack.top();
if ( get_priority(c) > get_priority(top))
{ stack.push(c); break; }
else
{
top= stack.top(); stack.pop();
item.type = is_op; item.u.op = top;
ls.push_back(item);
}
}
}
void right_handle( stack<char> &stack, list<LS_ITEM> &list)
{
char top;
LS_ITEM item;
while ( !stack.empty() )
{
top=stack.top();
stack.pop();
if ( top== '(' )
break;
item.type= is_op;
item.u.op= top;
list.push_back(item);
}
}
int calc( int x, int y, char method)
{
switch (method)
{
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/': return x / y;
}
return 0;
}
void print_list(list<LS_ITEM> &ls)
{
for ( list<LS_ITEM>::iterator it=ls.begin(); it != ls.end(); it++)
{
if ( it->type== is_op)
cout << it->u.op << " ";
else
cout << it->u.n << " " ;
}
}
//计算后缀表达式的值,输入参数和输出参数都是ls
void calc_on_list( list<LS_ITEM> &ls)
{
int n1,n2,r;
list<LS_ITEM>::iterator pre; // previous node
list<LS_ITEM>::iterator op=ls.begin(); // for point to operator
while (ls.size()>1 )
{
while ( op != ls.end() )
{
if ( op->type== is_op )
break;
op++;
}
pre=op;
pre--; n2= pre->u.n;
pre--; n1= pre->u.n;
r= calc( n1, n2, op->u.op);
op->type= is_num;
op->u.n = r;
pre=op; pre--; ls.erase(pre);
pre=op; pre--; ls.erase(pre);
}
}
// 将中缀表达式src,转化为后缀表达式,存入ls
void convert(const char *src, stack<char> &stack, list<LS_ITEM> &ls)
{
const char *p;
char c,top;
LS_ITEM item;
p=src;
while (*p!=0)
{
c=*p++;
if ( is_number(c) )
{
item.type= is_num;
item.u.n = c-'0';
ls.push_back(item);
}
else
{
switch (c)
{
case '+': case '-': case '*': case '/':
operator_handle(stack,c,ls); break;
case '(':
stack.push(c); break;
case ')':
right_handle(stack,ls); break;
default:
printf("wrong char"); break;
}
}
}
while (!stack.empty() )
{
top= stack.top();
item.type= is_op;
item.u.op= top;
ls.push_back(item);
stack.pop();
}
}
void test_convert_suffix_expression()
{
char *string="8+(3-1)*5"; // result is :8 3 1 - 5 * +
//char *string="3+(2-5)*6/3"; // result is "3 2 5 - 6 *3 /+"
stack<char> stack;
list<LS_ITEM> ls;
convert(string,stack,ls);
cout << "source=\"" << string << "\"" << endl ;
cout << "suffix form is \"" ;
print_list(ls);
cout << "\"" << endl ;
calc_on_list( ls);
cout << "result=";
print_list(ls);
}