数据结构学习笔记2——用栈计算后缀(postfix)表达的完整代码

来源:互联网 发布:淘宝樱花牌油画棒 编辑:程序博客网 时间:2024/04/30 07:07

实现《数据结构与算法分析 C++描述》3.6.3节的“后缀表达式”算法。

后缀表达式是类似于这样的表达式:6 5 2 3 + 8 * + 3 + *

求值过程为:当遇到一个数字时就将其压入栈中,在遇到一个操作符时,该操作符就作用于从该栈弹出的两个数字上,再将所得结果压入栈中。

为实现这一算法,需要用到上一节实现的栈,当然,为了方便使用,我们给上一节的栈增加了一个成员函数size()用于返回栈的大小

文件结构如下:


SeqStack_VT开头的文件是为了实现栈,都是上一节已经介绍过的.postfix中放的是后缀表达式运算算法。main.cpp中是主函数,测试算法是否能正常运行。


完整代码如下:

SeqStack_VT.h:模板的定义体

/********************************************************/// 用vector和模板实现顺序栈(Sequence Stack)的数据定义// 可以不用限制数据的最大个数和数据类型/********************************************************/#pragma once#include "Public.h"//定义顺序栈类,数据用vector存储,VT is short for Vector_Templatetemplate<class dataType>class Stack_VT{public:Stack_VT() :top_index(-1) {}        //默认构造函数void push(dataType const& elem);//压入新成员,放在栈顶void pop();//删除栈顶成员dataType top();//返回栈顶成员void clear();//清空栈bool isEmpty();//判断栈是否为空void print(ostream& out);//打印所有栈成员size_t size();                      //返回栈的大小(现存的元素个数)private:vector<dataType> data;//用于存储数据的数组int      top_index;//栈顶所在的数组下标};

SeqStack_VT_Def.h:模板的成员函数实现

/********************************************************/// 用Vector和模板实现顺序栈(Sequence Stac)类Stack_VT的成员函数定义// 模板版本,存储任意类型和任意长度数据/********************************************************/#pragma once#include "SeqStack_VT.h"//压入数据template <class dataType>void Stack_VT<dataType>::push(dataType const& elem){// vector的back就是栈的topdata.push_back(elem);top_index++;}//弹出数据template <class dataType>void Stack_VT<dataType>::pop(){if (!isEmpty()){data.pop_back();top_index--;}}//获取栈顶成员template <class dataType>dataType Stack_VT<dataType>::top(){if (!isEmpty()){return data[top_index];}else{//错误应该如何处理??cout << "访问空栈的成员" << endl;return data[-1];}}//清空栈template <class dataType>void Stack_VT<dataType>::clear(){top_index = -1;}//判断栈是否为空template <class dataType>bool Stack_VT<dataType>::isEmpty(){if (top_index >= 0){return false;}else{return true;}}//返回栈的大小template <class dataType>size_t Stack_VT<dataType>::size(){return top_index + 1;}//打印所有栈成员template <class dataType>void Stack_VT<dataType>::print(ostream& out){if (isEmpty()){out << "The stack is empty!" << endl;}else{for (size_t index = 0; index != top_index + 1; index++){out << data[index] << endl;}}}

postfix.h:后缀算法头文件

/********************************************************/// 《数据结构与算法分析》3.6.3节 后缀记法的实现/********************************************************/#pragma once#include "SeqStack_VT_Def.h"double postfix_cal(string const& str);

postfix.cpp:后缀算法实现

/********************************************************/// 《数据结构与算法分析》3.6.3节 后缀记法的实现/********************************************************/#include "SeqStack_VT_Def.h"/********************************************************/// 全局变量定义/********************************************************///只支持四则运算static const char Operator[4] = {'+','-','*','/'};static const char blank[4] = {'\n','\t','\40','\r' };vector<char> vBlank(blank, blank + 4);vector<char> vOperator(Operator, Operator + 4);/********************************************************/// 函数声明/********************************************************/int check_string(string const& str);int str2vector(string const& str, vector<string> & sVector);int process(vector<string> & sVector,double &result);int cal(Stack_VT<string> &stack_str, string const &oper, double &result);double postfix_cal(string const& str){int iErrorCode = 0;double result = 0.0;vector<string> sVector;cout << str << endl;// 1,检查输入的字符串中是否有非法字符iErrorCode = check_string(str);// 2,将字符串按空白字符分隔,存进vector<string>中if (0 == iErrorCode){iErrorCode = str2vector(str, sVector);}// 3,计算if (0 == iErrorCode){iErrorCode = process(sVector,result);}// 4,返回结果if (0 == iErrorCode){return result;}else{cout << "ERROR! iErrorCode = " << iErrorCode<< endl;return 0;}}//输入的字符串中只能含有0~9的数字、小数点、运算符和空白字符int check_string(string const& str){bool bExist = false;vector<char> accept_char(Operator[0],Operator[3]);accept_char.push_back('.');accept_char.insert(accept_char.end(), blank[0], blank[3]);for (string::const_iterator iter = str.cbegin(); iter != str.cend(); iter++){if (*iter < '0' && *iter > '9'){//没找到时,find返回第二个实参//字符既不在0到9之间,又不是其他的可能字符,报错if (accept_char.cend() == find(accept_char.cbegin(), accept_char.cend(), *iter)){cout << "The error input!" << endl;return 1;}}}//能安全走到这里就说明没有非法字符return 0;}int str2vector(string const& str, vector<string> & sVector){string cur_str;//当前的字符串for (string::const_iterator iter = str.cbegin(); iter != str.cend(); iter++){//输入的非空白字符if (vBlank.cend() == find(vBlank.cbegin(),vBlank.cend(),*iter)){cur_str.push_back(*iter);//到最后一个字符if (str.cend() == (iter + 1)){sVector.push_back(cur_str);}else{//本字符是运算符,或者,如果下一个字符是运算符号if ((vOperator.cend() != find(vOperator.cbegin(), vOperator.cend(), *iter) )||(vOperator.cend() != find(vOperator.cbegin(), vOperator.cend(), *(iter + 1)))){sVector.push_back(cur_str);cur_str.clear();}}}else{//防止第一个字符就是空白字符,或者连续出现的空白字符//将空字符串push进stack会怎么样?if (!cur_str.empty()){sVector.push_back(cur_str);cur_str.clear();}}}//如果结果里的第一个字符就是运算符,报错char oper = (*sVector.begin())[0];if (vOperator.cend() != find(vOperator.cbegin(), vOperator.cend(), oper)){cout << "第一个字符就是运算符,Error!" << endl;return 2;}//如果结果里的最后一个字符不是运算符,报错char oper_last = sVector[sVector.size() - 1][0];if (vOperator.cend() == find(vOperator.cbegin(), vOperator.cend(), oper_last)){cout << "最后一个字符不是运算符,Error!" << endl;return 2;}return 0;}int process(vector<string> & sVector , double &result){int iErrorCode = 0;Stack_VT<string> stack_str; string cur_oper;vector<string>::iterator iter = sVector.begin();for (vector<string>::iterator iter = sVector.begin();(iter != sVector.end()) && (0 == iErrorCode);iter++){//不是操作符就压入栈中,直到遇到操作符if (vOperator.cend() == find(vOperator.cbegin(), vOperator.cend(), (*iter)[0])){stack_str.push(*iter);}else{//保存当前的运算符cur_oper = *iter;//不光进行运算,还将已经用过的数字剔除掉,并将新的结果压入,即会改变stack_striErrorCode = cal(stack_str, cur_oper, result);}}return iErrorCode;}int cal(Stack_VT<string> &stack_str, string const &cur_oper, double &result){int iErrorCode = 0;double d1, d2;//因为只支持二目运算符,所以stack_str中必须至少包含两个数字if (stack_str.size() < 2){iErrorCode = 3; cout << "栈中的数字太少!" << endl;stack_str.print(cout);}if (0 == iErrorCode){d1 = atof(stack_str.top().c_str());stack_str.pop();//用了就扔d2 = atof(stack_str.top().c_str());stack_str.pop();char oper = cur_oper[0];switch (oper){case '+':result = d1 + d2;break;case '-':result = d1 - d2;break;case '*':result = d1*d2;break;case '/':if (d2 == 0.0){iErrorCode = 4;result = 0;}else{result = d1 / d2;}break;default:iErrorCode = 5;break;}char result_str[10];sprintf_s(result_str, 10,"%.3lf", result);stack_str.push(result_str);//stack_str.print(cout);}return iErrorCode;}

main.cpp:主函数,调用我们编写的函数

/********************************************************/// 主函数// 用于测试编写的各函数与数据结构/********************************************************/#include "SeqStack_VT_Def.h"#include "postfix.h"int main(){/********************************************************/// 2,《数据结构与算法分析》3.6.3节 后缀记法的实现/********************************************************/string str = "6 5 2 3+8*+3+*";cout << "result = " << postfix_cal(str) << endl;system("pause");return 0;}


运行结果如下:



0 0
原创粉丝点击