用堆栈机实现表达式运算

来源:互联网 发布:美工培训班学费多少 编辑:程序博客网 时间: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