后缀表达式也称逆波兰表达式。在计算机的数值计算和文本分析中经常使用。
本程序用C语言实现了高效地计算后缀表达式。
/* 由于编译器的原因,本程序中的部分0需要改为NULL或'/0'。*/
#include <stdio.h>
#include <malloc.h>
/* 结构:Operand
功能:建立链式栈,用于计算后缀表达式
注意: OperandStack变量在定义时一定要初始化为(OperandStack operandStack = 0;),
在使用结束后:
如果OperandStack变量的值为可以不销毁,
否则一定要销毁(DestroyOperandStack(&operandStack);)。
销毁后的链式栈为空,可以正常使用。*/
typedef struct operand
{
double operand_;
struct operand * link_;
}Operand, * OperandStack;
void PushOperandStack(OperandStack * pOperandStack, double operand)
{
Operand * p = (Operand *)malloc(sizeof(Operand));
p->operand_ = operand;
p->link_ = *pOperandStack;
*pOperandStack = p;
}
double PopOperandStack(OperandStack * pOperandStack)
{
Operand * p = *pOperandStack;
double result = p->operand_;
*pOperandStack = p->link_;
free(p);
return result;
}
void DestroyOperandStack(OperandStack * pOperandStack)
{
Operand * p = *pOperandStack;
Operand * q;
while(q = p)
{
p = p->link_;
free(q);
}
*pOperandStack = 0;
}
/* 结构:DataType(结构Node中成员变量data_的类型)*/
typedef struct
{
double operand_;
char operator_;
}DataType;
/* 结构:Node(Node * 为结构Postfix中front_,rear_的类型)*/
typedef struct node
{
DataType data_;
struct node * link_;
}Node;
/* 结构:Postfix
功能:建立链式队列,用于存储和表示后缀表达式
注意: Postfix变量在定义时一定要初始化为(Postfix postfix = {0};)。
Postfix对应的链式队列为空的充分必要条件是== postfix.front_。
Postfix变量中成员变量front_和rear_只能同时为,或同时不为。
在使用结束后:
如果Postfix变量中成员变量front_的值为可以不销毁,
否则一定要销毁(DestroyPostfix(&postfix);)。
销毁后的链式队列为空,可以正常使用。*/
typedef struct
{
Node * front_;
Node * rear_;
}Postfix;
void PushPostfixOperand(Postfix * pPostfix, double operand0)
{
Node * p = (Node *)malloc(sizeof(Node));
p->data_.operand_ = operand0;
p->data_.operator_ = 0;
p->link_ = 0;
if(pPostfix->rear_)
pPostfix->rear_->link_ = p;
else
pPostfix->front_ = p;
pPostfix->rear_ = p;
}
void PushPostfixOperator(Postfix * pPostfix, char operator0)
{
Node * p = (Node *)malloc(sizeof(Node));
p->data_.operand_ = 0;
p->data_.operator_ = operator0;
p->link_ = 0;
/* 如果pPostfix->rear_不为,那么pPostfix->front_不为,
那么pPostfix对应的链式队列不为空。*/
if(pPostfix->rear_)
pPostfix->rear_->link_ = p;
else
/* 在pPostfix对应的链式队列为空时,要让pPostfix->front_指向新开辟的空间。*/
pPostfix->front_ = p;
pPostfix->rear_ = p;
}
DataType PopPostfix(Postfix * pPostfix)
{
Node * p = pPostfix->front_;
DataType result = p->data_;
pPostfix->front_ = p->link_;
free(p);
return result;
}
void DestroyPostfix(Postfix * pPostfix)
{
Node * p = pPostfix->front_;
Node * q;
while(q = p)
{
p = p->link_;
free(q);
}
pPostfix->front_ = 0;
pPostfix->rear_ = 0;
}
typedef enum
{
Success,
Failure,
}Boolean;
/* 函数名:CalcPostfix
功能:计算Postfix变量对应的后缀表达式的值。
注意: CalcPostfix改变了Postfix变量对应的后缀表达式。*/
Boolean CalcPostfix(Postfix * postfix, double * pOperand)
{
/* 顺序扫描表达式的每一项,然后根据它的类型做如下相应操作:
如果该项时操作数,则将其压入栈中;
如果该项时操作符<op>,则连续从栈中退出两个操作数Y和X,形成运算指令X<op>Y,并将计算结果重新压入栈中。
当表达式的所有项都扫描并处理完后,栈顶存放的就是最后的计算结果。*/
Operand * operandStack = 0;
while(postfix->front_)
{
DataType data;
if((data = PopPostfix(postfix)).operator_)
{
double operand0;
double operand1;
if(0 == operandStack)return Failure;
operand0 = PopOperandStack(&operandStack);
if(0 == operandStack)return Failure;
switch(data.operator_)
{
case '+': operand1 = PopOperandStack(&operandStack) + operand0; break;
case '-': operand1 = PopOperandStack(&operandStack) - operand0; break;
case '*': operand1 = PopOperandStack(&operandStack) * operand0; break;
case '/':
if(operand0)
{
operand1 = PopOperandStack(&operandStack) / operand0;
break;
}
goto CalcPostfixFailure;
default: goto CalcPostfixFailure;
}
PushOperandStack(&operandStack, operand1);
}
else
PushOperandStack(&operandStack, data.operand_);
}
*pOperand = PopOperandStack(&operandStack);
if(0 == operandStack)
return Success;
/* 为了提高效率,并减少代码量,此处使用了goto语句。*/
CalcPostfixFailure:
DestroyOperandStack(&operandStack);
return Failure;
}
int main(int argc, char *argv[]) /* 测试代码*/
{
Postfix postfix = {0}; /* Postfix变量在定义时一定要初始化为*/
double s;
/* 中缀表达式( 1.0 + 2.0 ) 对应的后缀表达式为( 1.0 2.0 + ) */
PushPostfixOperand(&postfix, 1.0);
PushPostfixOperand(&postfix, 2.0);
PushPostfixOperator(&postfix, '+');
if(Success == CalcPostfix(&postfix, &s))
printf("%lf/n", s); /* 3 */
else
printf("Failure!/n");
DestroyPostfix(&postfix);
/* 中缀表达式( 1.1 + 2.2 * (3.3 - 4.4) - 5.5 / 6.6 )
对应的后缀表达式为( 1.1 2.2 3.3 4.4 - * + 5.5 6.6 / - ) */
PushPostfixOperand(&postfix, 1.1);
PushPostfixOperand(&postfix, 2.2);
PushPostfixOperand(&postfix, 3.3);
PushPostfixOperand(&postfix, 4.4);
PushPostfixOperator(&postfix, '-');
PushPostfixOperator(&postfix, '*');
PushPostfixOperator(&postfix, '+');
PushPostfixOperand(&postfix, 5.5);
PushPostfixOperand(&postfix, 6.6);
PushPostfixOperator(&postfix, '/');
PushPostfixOperator(&postfix, '-');
if(Success == CalcPostfix(&postfix, &s))
printf("%lf/n", s); /* -2.153333 */
else
printf("Failure!/n");
DestroyPostfix(&postfix);
/* 中缀表达式(1.0 / 0.0) 对应的后缀表达式为( 1.0 0.0 / ) */
PushPostfixOperand(&postfix, 1.0);
PushPostfixOperand(&postfix, 0.0);
PushPostfixOperator(&postfix, '/');
if(Success == CalcPostfix(&postfix, &s))
printf("%lf/n", s);
else
printf("Failure!/n"); /* Failure! */
DestroyPostfix(&postfix);
/* 中缀表达式( 1.234567 + 12.34567 - 123.4567 * 1234.567 / 12345.67)
对应的后缀表达式为( 1.234567 12.34567 + 123.4567 1234.567 * 12345.67 / -) */
PushPostfixOperand(&postfix, 1.234567);
PushPostfixOperand(&postfix, 12.34567);
PushPostfixOperator(&postfix, '+');
PushPostfixOperand(&postfix, 123.4567);
PushPostfixOperand(&postfix, 1234.567);
PushPostfixOperator(&postfix, '*');
PushPostfixOperand(&postfix, 12345.67);
PushPostfixOperator(&postfix, '/');
PushPostfixOperator(&postfix, '-');
if(Success == CalcPostfix(&postfix, &s))
printf("%lf/n", s); /* 1.234567 */
else
printf("Failure!/n");
DestroyPostfix(&postfix);
return 0;
}
参考资料:
[1]计算机学科专业基础综合 考试大纲解析 2010年版 本书编写组.全国硕士研究生入学统一考试 计算机学科专业基础综合 考试大纲解析 2010年版.北京:高等教育出版社