用堆栈机实现表达式运算

前言

用堆栈机模拟实现了一个表达式求值.
使用了双栈.
没有测试除法, 以后再完善.
不过, 以后用二叉树实现了逆波兰表达式的求值, 这个版本也就不想更新了.

测试程序

/// @file StackMachine.cpp : Defines the entry point for the console application.
/// @brief 
/**
exam_4
2.用堆栈机实现表达式运算
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)





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值