中缀表达式转换为前缀表达式的3种方法,链接如下:
http://wenku.baidu.com/view/0a1d3b365a8102d276a22f85.html
快要开始工作了,人生的第一份工作要格外重视,毕竟要有一个好的开始嘛。所以抽几天时间复习一下数据结构。看到堆栈部分,有一个运用堆栈的列子,表达式的中缀和前缀后缀的转换,刚开始找工作面试和笔试都遇到了这样的问题,以前模模糊糊的,现在搞明白了
一.表达式的三种形式:
中缀表达式:运算符放在两个运算对象中间,这是我们书写的时候最熟悉的一种形式,如:(2+1)*3
后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:2 1 + 3 *
前缀表达式:同后缀表达式一样,不包含括号,运算符放在两个运算对象的前面,如:* + 2 1 3
二.中缀表达式向后缀和前缀表达式的转换
转化的过程需要一个辅助的运算符堆栈op。并且要预先给运算符设置好运算的优先级如下所示:
struct
{
char
ch;
int
pri;
}
lpri[]={{
'='
,0},{
'('
,1},{
'*'
,5},{
'/'
,5},{
'+'
,3},{
'-'
,3},{
')'
,6}},
rpri[]={{
'='
,0},{
'('
,6},{
'*'
,4},{
'/'
,4},{
'+'
,2},{
'-'
,2},{
')'
,1}};
|
我们可以看到同一个运算符作为左(对应lpri数组)、右(对应rlpri数组)运算符时他们的优先级不同,这是为了实现表达式求值时"从左到右计算"的规定设计的。为了方便算法的实现,在op堆栈的栈地存放的是'='作为终结。
将算术表达式exp转换成后缀表达式postexp的过程如下:
初始化运算符堆栈op;
将
'='
进栈;
从
exp
读取字符ch;
while
(ch!=
'\0'
)
{
if
(ch不是运算符)
将后续的所有数字均依次存放到postexp中,并以字符
'#'
标志数值串的结束;
else
switch
(precede(op的栈顶运算符,ch))
{
case
'<'
:
//栈顶运算符优先级低
将ch进栈;
从
exp
读取下一个字符ch;
break
;
case
'='
:
退栈;
从
exp
读取下一个字符ch;
break
;
case
'>'
:
退栈运算符并将其存放到postexp中;
break
;
}
}
若字符串
exp
扫描完毕,则将运算符栈op中
'='
之前的所有运算符依次出栈并存放到
postexp中。最后得到后缀表达式postexp。
|
具体的C语言代码如下:
#include "stdafx.h"
#include <iostream>
#define MaxOp 10
#define MaxSize 50
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)
{
int
i;
for
(i=0;i<MaxOp;i++)
if
(lpri[i].ch==op)
return
lpri[i].pri;
}
int
rightpri(
char
op)
{
int
i;
for
(i=0;i<MaxOp;i++)
if
(rpri[i].ch==op)
return
rpri[i].pri;
}
int
isOp(
char
ch)
{
if
(ch==
'('
||ch==
')'
||ch==
'*'
||ch==
'/'
||ch==
'+'
||ch==
'-'
)
return
1;
else
return
0;
}
int
precede(
char
op1,
char
op2)
{
if
(leftpri(op1)==rightpri(op2))
return
0;
else
if
(leftpri(op1)<rightpri(op2))
return
-1;
else
return
1;
}
int
precedeT(
char
op1,
char
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[])
{
typedef
struct
{
char
data[MaxSize];
int
top;
}OP;
OP *op=(OP *)
malloc
(
sizeof
(OP));
int
i=0;
op->top=-1;
op->top++;
op->data[op->top]=
'='
;
while
(*
exp
!=
'\0'
)
{
if
(!isOp(*
exp
))
{
while
(*
exp
>=
'0'
&&*
exp
<=
'9'
)
{
postexp[i++]=*
exp
;
exp
++;
}
postexp[i++]=
'#'
;
}
else
switch
(precede(op->data[op->top],*
exp
))
{
case
-1:
op->data[++op->top]=*
exp
;
exp
++;
break
;
case
0:
op->top--;
exp
++;
break
;
case
1:
postexp[i++]=op->data[op->top--];
break
;
}
}
while
(op->data[op->top]!=
'='
)
{
postexp[i++]=op->data[op->top--];
}
postexp[i]=
'\0'
;
}
void
transT(
char
*
exp
,
char
postexp[])
{
typedef
struct
{
char
data[MaxSize];
int
top;
}OP;
OP *op=(OP *)
malloc
(
sizeof
(OP));
int
i=0;
op->top=-1;
op->top++;
op->data[op->top]=
'='
;
int
j=-1;
char
*p=
exp
;
while
(*p!=
'\0'
)
{
p++;
j++;
}
while
(j>-1)
{
if
(!isOp(
exp
[j]))
{
while
(
exp
[j]>=
'0'
&&
exp
[j]<=
'9'
)
{
postexp[i++]=
exp
[j];
j--;
}
postexp[i++]=
'#'
;
}
else
switch
(precedeT(
exp
[j],op->data[op->top]))
{
case
-1:
op->data[++op->top]=
exp
[j];
j--;
break
;
case
0:
op->top--;
j--;
break
;
case
1:
postexp[i++]=op->data[op->top--];
break
;
}
}
while
(op->data[op->top]!=
'='
)
{
postexp[i++]=op->data[op->top--];
}
postexp[i]=
'\0'
;
}
float
compvalue(
char
*postexp)
{
typedef
struct
{
float
data[MaxSize];
int
top;
}OP;
float
a,b,c,d;
OP *st = (OP *)
malloc
(
sizeof
(OP));
st->top=-1;
while
(*postexp!=
'\0'
)
{
switch
(*postexp)
{
case
'+'
:
a=st->data[st->top--];
b=st->data[st->top--];
c=a+b;
st->data[++st->top]=c;
break
;
case
'-'
:
a=st->data[st->top--];
b=st->data[st->top--];
c=b-a;
st->data[++st->top]=c;
break
;
case
'*'
:
a=st->data[st->top--];
b=st->data[st->top--];
c=b*a;
st->data[++st->top]=c;
break
;
case
'/'
:
a=st->data[st->top--];
b=st->data[st->top--];
if
(a!=0)
{
c=b/a;
st->data[++st->top]=c;
}
else
{
printf
(
"\0除零错误!\n"
);
exit
(0);
}
break
;
default
:
d=0;
while
(*postexp>=
'0'
&&*postexp<=
'9'
)
{
d=10*d + *postexp -
'0'
;
postexp++;
}
st->data[++st->top]=d;
break
;
}
postexp++;
}
return
st->data[st->top];
}
float
compvalueT(
char
*postexp)
{
typedef
struct
{
float
data[MaxSize];
int
top;
}OP;
float
a,b,c,d;
OP *st = (OP *)
malloc
(
sizeof
(OP));
st->top=-1;
while
(*postexp!=
'\0'
)
{
switch
(*postexp)
{
case
'+'
:
a=st->data[st->top--];
b=st->data[st->top--];
c=a+b;
st->data[++st->top]=c;
break
;
case
'-'
:
a=st->data[st->top--];
b=st->data[st->top--];
c=a-b;
st->data[++st->top]=c;
break
;
case
'*'
:
a=st->data[st->top--];
b=st->data[st->top--];
c=a*b;
st->data[++st->top]=c;
break
;
case
'/'
:
a=st->data[st->top--];
b=st->data[st->top--];
if
(b!=0)
{
c=a/b;
st->data[++st->top]=c;
}
else
{
printf
(
"\0除零错误!\n"
);
exit
(0);
}
break
;
default
:
d=0;
while
(*postexp>=
'0'
&&*postexp<=
'9'
)
{
d=10*d + *postexp -
'0'
;
postexp++;
}
st->data[++st->top]=d;
break
;
}
postexp++;
}
return
st->data[st->top];
}
int
_tmain(
int
argc, _TCHAR* argv[])
{
char
exp
[]=
"1+((2+3)*4)-5"
;
//char expT[]="1+((2+3)*4)-5";
//fanzhuan(exp,expT);
//printf("expT:%s\n",expT);
char
postexp[MaxSize];
char
postexpT[MaxSize];
trans(
exp
,postexp);
printf
(
"中缀表达式:%s\n"
,
exp
);
printf
(
"后缀表达式:%s\n"
,postexp);
transT(
exp
,postexpT);
printf
(
"前缀表达式:%s\n"
,postexpT);
printf
(
"后缀表达式的值:%f\n"
,compvalue(postexp));
printf
(
"前缀表达式的值:%f\n"
,compvalueT(postexpT));
return
0;
}
|
哈哈,上面的代码已经包括中缀转前后缀和前后缀的求值算法实现了。
前缀和后缀表达式转换方法的区别主要在,后缀是从左往右扫描exp,前缀反之。所以两者的左右运算符的划分是相反的。这一点还体现在求值的时候。