C高效计算后缀表达式

后缀表达式也称逆波兰表达式。在计算机的数值计算和文本分析中经常使用。

本程序用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;

/* 结构:NodeNode * 为结构Postfixfront_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>,则连续从栈中退出两个操作数YX,形成运算指令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年版.北京:高等教育出版社

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值