用堆栈机实现表达式运算
来源:互联网 发布:美工培训班学费多少 编辑:程序博客网 时间:2024/06/06 07:18
前言
用堆栈机模拟实现了一个表达式求值.
使用了双栈.
没有测试除法, 以后再完善.
不过, 以后用二叉树实现了逆波兰表达式的求值, 这个版本也就不想更新了.
测试程序
/// @file StackMachine.cpp : Defines the entry point for the console application./// @brief /**exam_42.用堆栈机实现表达式运算1 + 2 * 3 - 6 = 1*//** 逆波兰式的规则简化1. 遇到优先级低于栈顶的运算符, 直接清栈运算或者运算到(为止2. 遇到右括号, 直接清栈运算到左括号其他情况全部压栈*/#include <stdlib.h>#include <stdio.h>#include <assert.h>#include "LsStack.h"void fnTestDbList(); ///< 测试CLsLinkedList<T>双链表的所有接口int main(int argc, char* argv[]){ fnTestDbList(); return 0;}typedef int (*PFNCALC)(int, int);int fnCalc_add(int iLeft, int iRight){ return (iLeft + iRight);}int fnCalc_sub(int iLeft, int iRight){ return (iLeft - iRight);}int fnCalc_mul(int iLeft, int iRight){ return (iLeft * iRight);}int fnCalc_div(int iLeft, int iRight){ if (0 == iRight) { assert(0 != iRight); iRight = 1; } return (iLeft / iRight);}typedef struct _tag_operator{ _tag_operator(char cOperator, PFNCALC pfn, int iLevel) { this->cOperator = cOperator; this->pfn = pfn; this->iLevel = iLevel; } char cOperator; PFNCALC pfn; int iLevel; ///< 运算符优先级}TAG_OPERATOR;TAG_OPERATOR g_CalcOptAry[] = { TAG_OPERATOR('+', fnCalc_add, 0), TAG_OPERATOR('-', fnCalc_sub, 1), TAG_OPERATOR('*', fnCalc_mul, 2), TAG_OPERATOR('/', fnCalc_div, 3),};PFNCALC FindCalcFn(char cOpt){ int iTmp = 0; PFNCALC pfnRc = NULL; for (iTmp = 0; iTmp < (sizeof(g_CalcOptAry) / sizeof(g_CalcOptAry[0])); iTmp++) { if (cOpt == g_CalcOptAry[iTmp].cOperator) { pfnRc = g_CalcOptAry[iTmp].pfn; break; } } return pfnRc;}int CompareOptLevel(char cOptLeft, char cOptRight){ int iTmp = 0; int iLevelOptLeft = -1; int iLevelOptRight = -1; for (iTmp = 0; iTmp < (sizeof(g_CalcOptAry) / sizeof(g_CalcOptAry[0])); iTmp++) { if (cOptLeft == g_CalcOptAry[iTmp].cOperator) { iLevelOptLeft = g_CalcOptAry[iTmp].iLevel; } else if (cOptRight == g_CalcOptAry[iTmp].cOperator) { iLevelOptLeft = g_CalcOptAry[iTmp].iLevel; } if ((iLevelOptLeft >= 0) && (iLevelOptLeft >= 0)) { break; } } if (iLevelOptLeft == iLevelOptRight) { return 0; } if (iLevelOptLeft > iLevelOptRight) { return 1; } return -1;}bool isCanPushOpt(char cOpt){ bool bRc = false; int iTmp = 0; for (iTmp = 0; iTmp < (sizeof(g_CalcOptAry) / sizeof(g_CalcOptAry[0])); iTmp++) { if (cOpt == g_CalcOptAry[iTmp].cOperator) { bRc = true; break; } } return bRc;}bool isNum(char cIn){ return ((cIn >= '0') && (cIn <= '9'));}int c2int(char cIn){ int iRc = 0; if ((cIn >= '0') && (cIn <= '9')) { iRc = (cIn - '0'); } else { assert(0); } return iRc; }void fnTestDbList(){ int iTmp = 0; char cTmp = '\0'; int iIndex = 0; /// 最简化的处理, 一位数字, 延后考虑复杂情况 const char* pcInversePolandExpression = "1+2*3-6"; ///< 逆波兰表达式 CLsStack<int> stack_data; ///< 数据栈 CLsStack<char> stack_operator; ///< 运算符栈 CLsStack<char>::iterator itOpt; char cOptFirst = '\0'; char cOptSecond = '\0'; int iValFirst = '\0'; int iValSecond = '\0'; int iCalcResult = 0; PFNCALC pfnCalc = NULL; while ('\0' != *(pcInversePolandExpression + iIndex)) { cTmp = *(pcInversePolandExpression + iIndex); if (isNum(cTmp)) { stack_data.push(c2int(cTmp)); if (stack_operator.getLength() >= 2) { itOpt = stack_operator.begin(); cOptFirst = *itOpt++; cOptSecond = *itOpt; if (CompareOptLevel(cOptFirst, cOptSecond) >= 0) { if (stack_data.getLength() >= 2) { iValFirst = stack_data.pop(); iValSecond = stack_data.pop(); cOptFirst = stack_operator.pop(); pfnCalc = FindCalcFn(cOptFirst); assert(NULL != pfnCalc); if (NULL != pfnCalc) { iTmp = pfnCalc(iValFirst, iValSecond); stack_data.push(iTmp); } } } } } else { if (isCanPushOpt(cTmp)) { stack_operator.push(cTmp); } } iIndex++; } // 数据栈中为 1, 0 // 符号栈中为 + /// 此时, 栈中的数据运算符优先级都相同 /// 一次计算完 while (stack_operator.getLength() > 0) { cOptFirst = stack_operator.pop(); if (stack_data.getLength() >= 2) { iValFirst = stack_data.pop(); iValSecond = stack_data.pop(); pfnCalc = FindCalcFn(cOptFirst); assert(NULL != pfnCalc); if (NULL != pfnCalc) { iTmp = pfnCalc(iValFirst, iValSecond); stack_data.push(iTmp); } } } /// 计算完成, 数据栈中是计算结果 if (stack_data.getLength() >= 0) { iCalcResult = stack_data.pop(); printf("%s = %d\n", pcInversePolandExpression, iCalcResult); } else { printf("can't calculate result, please check input\n"); } printf("\n");}
模板实现
// LsStack.h: interface for the CLsLinkedList class.////////////////////////////////////////////////////////////////////////#if !defined(LSSTACK_H_82FEA8FE_F7B8_4CD7_A162_751580726632)#define LSSTACK_H_82FEA8FE_F7B8_4CD7_A162_751580726632#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include "LsDoublyLinkedList.h"/**栈 栈也是线性表. 栈是先进后出, 只操作栈顶的数据结构. 栈是可以回溯的 栈可以用来计算用来制作堆栈机, 用堆栈机算法来模拟逆波兰表达式的运算结果, 可以模拟汇编指令的执行, 用于虚拟机.实现方法 * 用链表类实现 继承于链表, 只在头部操作(增加,删除). * 用数组类实现 继承于数组, 只在尾部操作(增加,删除).*/template<typename T>class CLsStack : public CLsLinkedList<T>{public: CLsStack() { } virtual ~CLsStack() { } void push(T Element); T pop();};template<typename T>void CLsStack<T>::push(T Element){ addHead(Element);}template<typename T>T CLsStack<T>::pop(){ T Rc = (T)0; if (getLength() > 0) { Rc = *getHead(); removeHead(); } return Rc;}#endif // !defined(LSSTACK_H_82FEA8FE_F7B8_4CD7_A162_751580726632)
// LsDoublyLinkedList.h: interface for the CLsLinkedList class.////////////////////////////////////////////////////////////////////////#if !defined(LSDOUBLYLINKEDLIST_H_82FEA8FE_F7B8_4CD7_A162_751580726632)#define LSDOUBLYLINKEDLIST_H_82FEA8FE_F7B8_4CD7_A162_751580726632/**链表总结空间 链式存储时间复杂度 尽量避免提供非常量阶的接口 增加操作: O(1) 常量阶, 快 删除操作: O(1) 常量阶, 快 修改操作:O(1) 快(条件:知道位置, 用的是先前返回的位置类或结点指针) 查询操作:O(n) 线性阶, 慢 随机访问:O(n) 线性阶, 慢使用场合 * 问题规模不确定 * 随机访问频率低 * 数据更新频率高(主要指的是添加和删除操作)缺点 * 查询速度慢(数组和链表查询速度都慢)原生new的时间复杂度 new实现是线性阶. 调用的memset是线性阶, 有循环操作. HeapAlloc中没源码, 但是有循环操作, 是线性阶. new不影响时间增长率.结论 当算法中, new次数较少时, 可以忽略new对算法时间复杂度的影响. 当new次数较多时, 可以一次多new几个元素(e.g. 10个), 下次就不用new, 直接取已经new好的数据操作, 等用完了, 才再次new几个元素出来. 这样对new操作做优化, 等于自己做堆管理, 需要再做一个链表, 将new出来的10个一组的小块内存空间管理起来, 当一个类指针不用了, 就称为闲置空间, 放在内存池中. 下次不用再申请了, 可以复用. 等链表析构时, 链表的原生操作完成后, 再一块释放内存池.*/#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000/// ----------------------------------------------------------------------/// CLsLinkedList 双链表 定义/// ----------------------------------------------------------------------template <typename T>class CLsLinkedList {public: /// ---------------------------------------------------------------------- /// CLsLinkedNode 定义 /// ---------------------------------------------------------------------- /// LsDoublyLinkedList's Node template <typename T> struct CLsLinkedNode { friend CLsLinkedList<T>; ///< 不需要前向声明, 用到的时候才检查 friend CLsLinkedList<T>::iterator; private: CLsLinkedNode(T Elem) :m_Elem(Elem) ,m_pNext(NULL) ,m_pPrev(NULL) { } ~CLsLinkedNode() { } T m_Elem; //数据元素 CLsLinkedNode<T>* m_pPrev; //前驱 CLsLinkedNode<T>* m_pNext; //后继 }; /// ---------------------------------------------------------------------- /// 正向迭代器 定义 /// ---------------------------------------------------------------------- class iterator { friend class CLsLinkedList<T>; public: iterator() { m_pNode = NULL; } iterator(CLsLinkedNode<T>* pNode) { m_pNode = pNode; } iterator operator++() { m_pNode = m_pNode->m_pNext; return m_pNode; } iterator operator++(int) { CLsLinkedNode<T> *pTemp = m_pNode; m_pNode = m_pNode->m_pNext; return pTemp; } iterator operator--() { m_pNode = m_pNode->m_pPrev; return m_pNode; } iterator operator--(int) { CLsLinkedNode<T> *pTemp = m_pNode; m_pNode = m_pNode->m_pPrev; return pTemp; } T& operator* () { return m_pNode->m_Elem; } bool operator!= (const iterator& obj) { return m_pNode != obj.m_pNode; } bool operator== (const iterator& obj) { return m_pNode == obj.m_pNode; } private: CLsLinkedNode<T>* GetNode() { return m_pNode; } private: CLsLinkedNode<T>* m_pNode; };public: iterator begin() { return m_pHead; } iterator end() { return NULL; }public: CLsLinkedList(); virtual ~CLsLinkedList(); /// 只提供O(1)的接口^_^ iterator getTail() const; iterator getHead() const; inline bool isEmpty() const; inline size_t getLength() const; //表长 void clear(); iterator addTail(T newElem); bool removeTail(); iterator addHead(T newElem); bool removeHead(); T getAt(iterator it) const; void setAt(iterator it, T newElem); bool removeAt(iterator it); bool insert(iterator it, T newElem);private: CLsLinkedNode<T>* m_pHead; //头结点 CLsLinkedNode<T>* m_pTail; //尾结点 size_t m_nLength;};/// ----------------------------------------------------------------------/// CLsLinkedList 实现/// ----------------------------------------------------------------------template <typename T>inline size_t CLsLinkedList<T>::getLength() const{ return m_nLength;}template <typename T>inline bool CLsLinkedList<T>::isEmpty() const{ return (NULL == m_pHead) ? true : false;}template <typename T>CLsLinkedList<T>::CLsLinkedList():m_pHead(NULL),m_pTail(NULL),m_nLength(0){}template <typename T>CLsLinkedList<T>::~CLsLinkedList(){ clear();}template <typename T>void CLsLinkedList<T>::clear(){ while (!isEmpty()) { removeTail(); }}template <typename T>T CLsLinkedList<T>::getAt(CLsLinkedList::iterator it) const{ return *it;}template <typename T>void CLsLinkedList<T>::setAt(CLsLinkedList::iterator it, T newElem){ *it = newElem;}template <typename T>bool CLsLinkedList<T>::insert(CLsLinkedList::iterator it, T newElem){ CLsLinkedNode<T>* pNewNode = NULL; CLsLinkedNode<T>* pPrev = NULL; CLsLinkedNode<T>* pNext = NULL; pPrev = it.GetNode(); if (NULL == pPrev) { return false; } pNewNode = new CLsLinkedNode<T>(newElem); pNext = pPrev->m_pNext; /* 1 2 3 [6] 4 5 3.next = 6 4.prev = 6 6.prev = 3 6.next = 4 1 2 3 4 5 [6] */ pPrev->m_pNext = pNewNode; if (NULL != pNext) { pNext->m_pPrev = pNewNode; } pNewNode->m_pPrev = pPrev; pNewNode->m_pNext = pNext; m_nLength++; return true;}template <typename T>bool CLsLinkedList<T>::removeTail(){ bool bRc = false; CLsLinkedNode<T>* pPrev = NULL; if (NULL == m_pHead) { return false; } //1 2 [3] if (NULL != m_pTail) { pPrev = m_pTail->m_pPrev; if (NULL != pPrev) { pPrev->m_pNext = NULL; } else { m_pHead = NULL; } delete m_pTail; bRc = true; m_pTail = pPrev; m_nLength--; } return bRc;}template <typename T>bool CLsLinkedList<T>::removeHead(){ if (NULL == m_pHead) { return false; } //[1] 2 3 CLsLinkedNode<T>* pNext = m_pHead->m_pNext; if (NULL != pNext) { pNext->m_pPrev = NULL; } else { m_pTail = NULL; } delete m_pHead; m_nLength--; m_pHead = pNext; return true;}template <typename T>bool CLsLinkedList<T>::removeAt(CLsLinkedList::iterator it){ CLsLinkedNode<T>* pDelNode = it.GetNode(); CLsLinkedNode<T>* pPrev = NULL; CLsLinkedNode<T>* pNext = NULL; if ((NULL == m_pHead) || (NULL == pDelNode)) { return false; } /* 1 2 [3] 4 5 2.next = 4 4.prev = 2 [1] 2 3 4 5 1 2 3 4 [5] [1] */ pPrev = pDelNode->m_pPrev; pNext = pDelNode->m_pNext; if (NULL != pPrev) { pPrev->m_pNext = pNext; } else { m_pHead = pNext; } if (NULL != pNext) { pNext->m_pPrev = pPrev; } else { m_pTail = pPrev; } delete pDelNode; m_nLength--; return true;}template <typename T>CLsLinkedList<T>::iterator CLsLinkedList<T>::addTail(T newElem){ CLsLinkedList<T>::CLsLinkedNode<T>* pNewNode = new CLsLinkedList<T>::CLsLinkedNode<T>(newElem); //空表 if (NULL == m_pHead) { m_pHead = m_pTail = pNewNode; } else { //1 2 3 4 5 [6] //5.next = 6 6.prev = 5 tail = 6 m_pTail->m_pNext = pNewNode; pNewNode->m_pPrev = m_pTail; m_pTail = pNewNode; } m_nLength++; return pNewNode;}template <typename T>CLsLinkedList<T>::iterator CLsLinkedList<T>::addHead(T newElem){ CLsLinkedList<T>::CLsLinkedNode<T> *pNewNode = new CLsLinkedList<T>::CLsLinkedNode<T>(newElem); //空表 if (NULL == m_pHead) { m_pHead = m_pTail = pNewNode; } else { //[6] 1 2 3 4 5 //1.prev = 6 6.next = 1 head = 6 m_pHead->m_pPrev = pNewNode; pNewNode->m_pNext = m_pHead; m_pHead = pNewNode; } m_nLength++; return pNewNode;}template <typename T>CLsLinkedList<T>::iterator CLsLinkedList<T>::getTail() const{ return m_pTail;}template <typename T>CLsLinkedList<T>::iterator CLsLinkedList<T>::getHead() const{ return m_pHead;}#endif // !defined(LSDOUBLYLINKEDLIST_H_82FEA8FE_F7B8_4CD7_A162_751580726632)
0 0
- 用堆栈机实现表达式运算
- 堆栈实现表达式求值
- 用栈实现运算表达式
- 用栈实现表达式运算
- 用栈实现表达式运算
- 堆栈的应用:四则表达式运算
- 堆栈实现,计算后缀表达式
- 利用堆栈实现表达式求值
- 简单的用堆栈实现的表达式计算
- 关于用堆栈实现中后缀表达式计算的问题
- 用数组顺序栈实现表达式运算(中缀表达式)
- 用数组顺序栈实现表达式运算(后缀表达式)
- 堆栈的应用--计算机对运算表达式编译
- VB利用堆栈实现表达式计算
- 使用堆栈计算后缀表达式--java实现
- 数组作为堆栈实现表达式整型计算器
- 利用堆栈实现四则表达式运算器
- 利用堆栈实现后缀表达式求值
- Mysql事务隔离级别
- 黑马程序员——多线程篇
- linux里查看mysql的一些命令
- 一些软件设计的原则
- iOS开发之UIWebView网页视图和UITextField密码输入框光标自动跳转下一个
- 用堆栈机实现表达式运算
- 【linux】linux基础知识的总结
- [IT与培训]IT培训与企业建设的思路
- 开源大数据引擎:Greenplum 数据库架构分析
- android 奔溃日志保存和上传
- Java Day9
- Python Binary Search
- oracle之pl/sql编程
- MySQL:having的作用