1. 程式人生 > >表示式求值(中綴轉字尾及字尾表示式求值)

表示式求值(中綴轉字尾及字尾表示式求值)

。中綴表示式轉字尾表示式:

中綴表示式轉字尾表示式遵循以下原則:

1.遇到運算元,直接輸出;
2.棧為空時,遇到運算子,入棧;
3.遇到左括號,將其入棧;
4.遇到右括號,執行出棧操作,並將出棧的元素輸出,直到彈出棧的是左括號,左括號不輸出;
5.遇到其他運算子’+”-”*”/’時,彈出所有優先順序大於或等於該運算子的棧頂元素,然後將該運算子入棧;
6.最終將棧中的元素依次出棧,輸出。
經過上面的步驟,得到的輸出既是轉換得到的字尾表示式。
舉例:a+b*c+(d*e+f)g ———> abc

+de*f+g*+

圖示上述過程:

因為比較懶,而剛好在網上看到畫的還不錯的圖,所以就直接貼過來了哦。希望作者不要怪罪哦。。。
遇到a,直接輸出:

這裡寫圖片描述

遇到+,此時棧為空,入棧:
這裡寫圖片描述

遇到b,直接輸出:
這裡寫圖片描述
遇到*,優先順序大於棧頂符號優先順序,入棧:
這裡寫圖片描述

遇到c,輸出:
這裡寫圖片描述
到+,目前站內的與+優先順序都大於或等於它,因此將棧內的,+依次彈出並且輸出,並且將遇到的這個+入棧:
這裡寫圖片描述
遇到(,將其入棧:
這裡寫圖片描述

遇到d,直接輸出:
這裡寫圖片描述
遇到*,由於的優先順序高於處在棧中的(,因此入棧:
這裡寫圖片描述
遇到e,直接輸出:
這裡寫圖片描述
遇到+,棧頂的優先順序高於+,但是棧內的(低於+,將出棧輸出,+入棧:這裡寫圖片描述

遇到f,直接輸出:
這裡寫圖片描述
遇到),彈出棧頂元素並且輸出,直到彈出(才結束,在這裡也就是彈出+輸出,彈出(不輸出:
這裡寫圖片描述
遇到*,優先順序高於棧頂+,將*入棧
這裡寫圖片描述
遇到g,直接輸出: :
這裡寫圖片描述
此時已經沒有新的字元了,依次出棧並輸出操作直到棧為空:
這裡寫圖片描述

因為字尾表示式求值過程較為簡單:
所以在這裡我只進行簡單說明:
1.掃描字尾表示式:
①如果是數字,則讓其進棧
②若為操作符,則從棧中取出兩個運算元,先取出的作為右運算元,後取出的作為左運算元,然後進行該操作符的運算,並使其結果入棧。
③重複上述過程,直至表示式掃描完成。
2.最終棧中只留一個元素—–>即就是結果。

下面程式碼實現中綴轉字尾以及字尾表示式求值:

使用的棧是自定義棧(自己實現的):
//stack.h

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include<cassert>

//------------使用型別萃取來拷貝棧內元素-------------
struct _TrueType
{
    bool Get()
    {
        return true;
    }
};

struct _FalseType
{
    bool Get()
    {
        return false;
    }
};

template<class _Tp>
struct TypeTraits
{
    typedef _FalseType _IsPODType;
};

template<>
struct TypeTraits<bool>
{
    typedef _TrueType _IsPODType;
};

template<>
struct TypeTraits<int>
{
    typedef _TrueType _IsPODType;
};

template<>
struct TypeTraits<unsigned int>
{
    typedef _TrueType _IsPODType;
};

template<>
struct TypeTraits<char>
{
    typedef _TrueType _IsPODType;
};

template<>
struct TypeTraits< float >
{
    typedef _TrueType _IsPODType;
};

template<>
struct TypeTraits< double >
{
    typedef _TrueType _IsPODType;
};

template<>
struct TypeTraits<long>
{
    typedef _TrueType _IsPODType;
};

template<>
struct TypeTraits< unsigned long>
{
    typedef _TrueType _IsPODType;
};

template<class T>
void Copy(T* dst, T* src, size_t size)
{
    if (TypeTraits<T>::_IsPODType().Get())
    {
        memcpy(dst, src, size);
    }
    else
    {
        for (int i = 0; i < size; ++i)
        {
            dst[i] = src[i];
        }
    }
}

template<class T>
struct TypeTraits< T* >
{
    typedef _TrueType _IsPODype;
};

//-------------------------棧的基本操作----------------
template<class T>
class Stack
{
public:
    //建構函式
    Stack(int capacity = 10)
        :_pData(NULL)
        , _capacity(capacity)
        , _size(0)
    {
        _pData = new T[capacity];
    }

    //拷貝建構函式
    Stack(const Stack<T>& s)
        :_pData(new T[s._capacity])
        , _size(s._size)
        , _capacity(s._capacity)
    {
        for (int i = 0; i < _size; ++i)
        {
            _pData[i] = s._pData[i];
        }
    }

    //賦值運算子函式
    Stack& operator=(Stack<T> s)
    {
        std::swap(_pData, s._pData);
        _size = s._size;
        _capacity = s._capacity;
        return *this;
    }

    //入棧
    void Push(const T& data)
    {
        CheckCapacity();
        _pData[_size++] = data;
    }
    //出棧
    void Pop()
    {
        if (!Empty())
        {
            --_size;
        }
    }

    //獲取棧頂元素
    T& Top()
    {
        if (!Empty())
        {
            return _pData[_size - 1];
        }
    }

    const T& Top()const
    {
        if (!Empty())
        {
            return _pData[_size - 1];
        }
    }

    size_t Size()const
    {
        return _size;
    }

    bool Empty()const
    {
        return 0 == _size;
    }

    //解構函式(釋放資源)
    ~Stack()
    {
        if (_pData)
        {
            delete[] _pData;
            _pData = NULL;
        }
    }

private:
    //增容
    void CheckCapacity()
    {
        if (_size >= _capacity)
        {
            _capacity = 2 * _capacity + 3;
            T* tmp = new T[_capacity];
            //拷貝原資料
            //釋放舊空間
            //指向新空間
           //需要進行型別萃取
            Copy<T>(_pData, tmp, _size);
            delete[] _pData;
            _pData = tmp;
        }
    }

    T* _pData;
    int _capacity;
    int _size;
};

//----------------------------------------------------------
//需要用到的函式的宣告
int GetPriority(char ch, int flag);//獲取優先順序
bool IsOperator(char ch);//判斷是否為操作符
void prefixionToSuffix(char* dst, char* src);//中綴表示式轉字尾表示式
int  SuffixToValue(char *suffix, char *prefixion);//字尾表示式求值


中綴表示式轉字尾表示式:
//prefixionToSuffix.cpp

#include"Stack.h"

//flag為1時表示棧內優先順序  flag為0表示棧外優先順序
int GetPriority(char ch, int flag)
{
    if (ch == '+' || ch == '-')
    {
        if (flag)
        {
            return 3;
        }
        else
        {
            return 2;
        }
    }
    else if (ch == '*' || ch == '/' || ch == '%')
    {
        if (flag)
        {
            return 5;
        }
        else
        {
            return 4;
        }
    }
    else if (ch == '(')
    {
        if (flag)
        {
            return 1;
        }
        return 6;
    }
    else if (ch == ')')
    {
        if (flag)
        {
            return 6;
        }
        else
        {
            return 1;
        }
    }
}

bool IsOperator(char ch)
{
    if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%' || ch == '(' || ch == ')')
    {
        return true;
    }
    return false;
}

//中綴表示式轉字尾表示式
void prefixionToSuffix(char* dst, char* src)
{
    assert(dst);
    assert(src);
    Stack<char> s;
    char * cur = src;
    char* tmp = dst;
    while (*cur != '\0')
    {
        if (*cur >= '0' && *cur <= '9')
        {
            *tmp++ = *cur;
            cur++;
            continue;
        }
        else if (IsOperator(*cur))
        {
            if (s.Empty())//如果棧為空,直接入棧
            {
                s.Push(*cur);
                cur++;
            }
            else//如果棧不空,則需要判斷棧頂元素和當前操作符的優先順序
            {
                if (*cur == ')')
                {
                    while (*cur == ')' && s.Top() != '(')
                    {
                        *tmp++ = s.Top();
                        s.Pop();
                    }
                    s.Pop();
                    cur++;
                }
                if (GetPriority(*cur, 0) > GetPriority(s.Top(), 1))
                {
                    s.Push(*cur);
                    cur++;
                }
                else
                {
                    while (!s.Empty() && GetPriority(*cur, 0) < GetPriority(s.Top(), 1))
                    {
                        *tmp++ = s.Top();
                        s.Pop();
                    }
                    s.Push(*cur);
                    cur++;
                }

            }
        }
        else
        {
            *tmp++ = *cur++;
        }
    }
    while(!s.Empty())
    {
        *tmp++ = s.Top();
        s.Pop();
    }
}

字尾表示式求值:
//SuffixToValue.cpp

#include"Stack.h"

//12 3 4 + * 6 - 8 2 / +
int  SuffixToValue(char *suffix, char *prefixion)
{
    prefixionToSuffix(suffix, prefixion);

    Stack<int> s;
    char* cur = suffix;
    int res = 0;
    int tmp = 0;
    while (*cur != '\0')
    {
        if (*cur == '+' || *cur == '-' || *cur == '*' || *cur == '/' || *cur == '%')
        {
            char ch = *cur;
            int right = s.Top();
            s.Pop();
            int left = s.Top();
            s.Pop();
            switch (ch)
            {
            case '+':
                s.Push(left + right);
                break;
            case '-':
                s.Push(left - right);
                break;
            case '*':
                s.Push(left * right);
                break;
            case '%':
                s.Push(left % right);
                break;
            case '/':
                if (right)
                {
                    s.Push(left / right);
                }
                break;
            }
            cur++;
        }
        else if (*cur >= '0' && *cur <= '9')
        {
            res = 0;
            while (!isspace(*cur) && *cur >= '0' && *cur <= '9')
            {
                tmp = *cur - '0';
                res = res * 10 + tmp;
                cur++;
            }
            s.Push(res);
            //cur++;
        }
        else
        {
            cur++;
        }
    }
    if (!s.Empty())
    {
        res = s.Top();
        return res;
    }
}

main.cpp

#include"Stack.h"

void Test()
{
    char prefixion[] = "12 * (3 + 4) - 6 + 8 / 2 ";//儲存字首表示式
    char suffix[25] = {};//儲存字尾表示式
    int res = SuffixToValue(suffix, prefixion);
    cout << res << endl;
}

int main()
{
    Test();
    return 0;
}