数据结构:表达式计算(中缀变后缀及后缀计算)

一、目标与要求

实现表达式的计算功能。其中,表达式操作数为个位数,操作符包括加减乘除与括号。

二、工具/准备工作

编程使用VC6.0完成

三、实验分析

1、首先需构建一个栈类,这里选择顺序栈

2、其次需构建将中缀表达式转换为后缀表达式的函数,过程中还需构建操作符优先值函数

3、最后构建计算后缀的函数

计算后缀中需要将char型的操作数转换为float型

四、实验步骤

  1. 完成栈类的构建

成员数据包括

int count;                                       //元素个数

int maxsize;                            //最大个数

ElemType *elems;                          //存储元素

栈成员函数包括

   Stack(int size=DEFAULT_SIZE); //构造函数

   virtual ~Stack();                          //析构函数

   int Length() const;                       //返回栈元素个数

   bool Empty() const;                     //判断栈是否为空

   void Clear();                               //清空栈

   bool Push(const ElemType &e);    //插入元素e为新的栈顶元素

   bool Top(ElemType &e)const;      //用e返回栈顶元素

   bool Pop(ElemType &e);                    //删除栈顶元素,并用e返回栈顶元素

  1. 编写中缀变后缀的函数及相关操作符优先值函数,中缀变后缀大致思路如下:

先开一块char型数组p准备用于存放后缀表达式。

然后开启循环,逐个读取输入的中缀表达式的字符,如果读取的字符是操作数或“(”,直接进入p;如果是“+”“-”“*”“/”,栈空则直接进栈,栈非空则取栈顶元素,若栈顶元素的优先值小于读取字符的优先值,则将该字符进栈,如果栈顶元素的优先值大于等于读取字符的优先值,栈顶元素出栈并加入数组p,并取新的栈顶元素重复上述操作;如果读取的字符是“)”,则依次取栈顶元素出栈、加入p,直到遇到“(”为止,左右括号不加入p 。继续读取下一字符,直到遇到“=”为止。

循环结束后,将栈内元素从栈顶依次取出,加入到p,完成表达式中缀变后缀,p即为所求的后缀表达式。

  1. 编写计算后缀的函数,大致思路如下:

读取所求的后缀表达式,遇到操作数转化为float型直接进栈,遇到操作符则从栈顶取两个元素,进行该操作符相应的计算,将计算结果入栈后继续读取下一字符。循环结束后栈里的元素即为表达式的值。

4.编写main函数,调试、完善程序。

五、测试与结论

输入表达式,运行结果与实际值一致

当表达式中有除数为0时,程序予以提示

六、实验总结

算法能够实现表达式的计算,顺利完成了目标。表达式除了可以进行“+”“-”“*”“/”运算外,还可进行括号的运算。

独立编写了栈类、中缀转后缀、计算后缀三大部分,思路清晰。

感悟

  1. 数据结构的编程题,无论是代码复杂程度还是代码量,都比大一时的C++有较大提升,编程能力还需提高。
  2. 编程需要更加注重规范性,大一时编程常常忽略const等细节的使用,现在需要规范起来。
  3. 无论是在编写程序时还是调试程序时,都要注意中英文,尤其在调试程序输入时要切成英文。

具体代码如下:

include<iostream.h>
#include<math.h>
#include<string.h>
#define DEFAULT_SIZE 20


template<class ElemType>
class Stack
{protected:
int count;
int maxsize;
ElemType *elems;

public:
    Stack(int size=DEFAULT_SIZE);    //构造函数
    virtual ~Stack();                //析构函数
    int Length() const;                //返回栈元素个数
    bool Empty() const;                //判断栈是否为空
    void Clear();                    //清空栈
    bool Push(const ElemType &e);    //插入元素e为新的栈顶元素
    bool Top(ElemType &e)const;        //用e返回栈顶元素
    bool Pop(ElemType &e);            //删除栈顶元素,并用e返回栈顶元素
};

template<class ElemType>
Stack<ElemType>::Stack(int size)
{maxsize=size;
 elems=new ElemType[maxsize];
 count=0;
}

template<class ElemType>
Stack<ElemType>::~Stack()
{delete []elems;
}

template<class ElemType>
int Stack<ElemType>:: Length() const
{return count;
}

template<class ElemType>
bool Stack<ElemType>:: Empty() const
{return count==0;
}

template<class ElemType>
void Stack<ElemType>::Clear()
{count=0;
}

template<class ElemType>
bool Stack<ElemType>::Push(const ElemType &e)
{if(count==maxsize)
    {return 0;
    }
else
    {elems[count++]=e;
    return 1;
    }
}

template<class ElemType>
bool Stack<ElemType>::Top(ElemType &e) const
{if(Empty())
    {return 0;
    }
else
    {e=elems[count-1];
     return 1;
    }
}

template<class ElemType>
bool Stack<ElemType>::Pop(ElemType &e)
{if(Empty())
    {return 0;
    }
else
    {e=elems[count-1];
     count--;
     return 1;
    }
}

int y(char a)            //操作符优先值
{if(a=='-'||a=='+') return 1;
 else if(a=='*'||a=='/') return 2;
 else if(a=='(') return 0;
 else {cout<<"请检查表达式是否正确"<<endl;return -1;}
}

void Transform(char *e)    //将中缀转为后缀
{char p[DEFAULT_SIZE],t;
 Stack<char> str;
 int j=0;
for(int i=0;i<strlen(e)-1;i++)
    {if(48<=e[i]&&e[i]<=57)
        {p[j++]=e[i];
        }
    else if(e[i]==')')
        {while(1)
            {str.Pop(t);
            if(t!='(')
            p[j++]=t;
            else
            break;
            }    
        }
    else if(e[i]=='(')
        {str.Push(e[i]);}
    else
    {    
        while(str.Empty()==0)
        {str.Top(t);
            if(y(t)>=y(e[i]))
            {str.Pop(t);
            p[j++]=t;
            }
            else break;
            
        }
        str.Push(e[i]);
    }
    }
while(str.Empty()==0)
    {str.Pop(t);
    p[j++]=t;
    }
p[j++]='=';
p[j]='\0';
strcpy(e,p);
}

float Calculator(char *e)    //计算后缀
{int i=0;
float z;
float t,t1,t2;

Stack<float> str;
    while (e[i]!='=')
    {if(48<=e[i]&&e[i]<=57)
        {t=e[i]-48;        //将字符数字转为浮点数
        str.Push(t);
        }
    else if(e[i]=='+')
        {str.Pop(t2);
        str.Pop(t1);
        t=t1+t2;
        str.Push(t);
        }
    else if(e[i]=='-')
        {str.Pop(t2);
        str.Pop(t1);
        t=t1-t2;
        str.Push(t);
        }
    else if(e[i]=='*')
        {str.Pop(t2);
        str.Pop(t1);
        t=t1*t2;
        str.Push(t);
        }
    else if(e[i]=='/')
        {    str.Pop(t2);
            str.Pop(t1);
            if(fabs(t2)>0.00001)
            {t=t1/t2;
            str.Push(t);
            }
            else
            {cout<<"除数为0,无法计算"<<endl;break;}
        }
    else{cout<<"请检查表达式是否正确"<<endl;break;
        }
    i++;
    }
str.Top(z);
return z;
}


void main()
{
char p[DEFAULT_SIZE];
cout<<"请输入表达式,以 = 结尾,注意输入法调为英文"<<endl;
cin.getline(p,DEFAULT_SIZE);
Transform(p);
cout<<Calculator(p)<<endl;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金锋986321

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值