棧和二叉樹的使用–四則運算

來源:互聯網
上載者:User

                   使用棧來檢測運算式括弧的匹配,使用二叉樹來儲存運算的中綴運算式,對錶達式樹進行後序遍曆得到尾碼運算式,運算得到運算式的值。

                   檢測配對使用棧儲存‘(’符號,當遇到一個‘)’,出棧,若棧空則出錯,運算式結束,棧非空也出錯。

                  

                  

3*5+2構造二叉樹如下

                  

                    四則運算有優先順序和結合關係,在構造二叉樹時影響構造的過程。優先順序高的運算子深度較深,在後序遍曆時,先遍曆到。

                    2+3*5構造二叉樹如下

    

          遇到括弧,將括弧中的看成一個子運算式,使用遞迴來解決。

         在中綴運算式轉換事的演算法描述如下:

         噹噹前的符號是運算數時,檢測當前是否有樹根,沒有則作為樹根,否則作為前一個運算子的右孩子,當根節點沒有右孩子則作為右孩子,有右孩子則作為右孩子的右元算數。如果是+或-,那它就是已知的最後一個運算子,將它作為根節點,原來的樹作為左子樹。如果是*或/,優先順序高,就要和根節點做比較,怎麼改變。如根節點是+或-,則則應該先運算,所以作為右子樹的根節點,原來的子樹作為它的左子樹。如果是同優先順序的,原來的先計算,當前最為根節點,原來作為左子樹。

        

#ifndef EXCEPTIONS_H#define EXCEPTIONS_H#include <exception>#include <iostream>/** * @brief The OutOfBoundary class 越界異常 */class OutOfBoundary : public std::exception{    friend std::ostream& operator << (std::ostream& os, const std::exception &obj) {        os << obj.what();        return os;    }public:    OutOfBoundary() throw(): exception(){}    ~OutOfBoundary() throw(){}    const char* what() const throw(){        return "out of boundary!";    }};/** * @brief The BadValue class 壞值異常 */class BadValue : public std::exception{    friend std::ostream& operator << (std::ostream& os, const BadValue &obj) {        os << obj.what();        return os;    }public:    BadValue() throw(): exception(){}    ~BadValue() throw(){}    const char* what() const throw(){        return "bad value!";    }};class MyException : public std::exception{public:    MyException(const char *_mes) throw() : exception(),info(_mes) {}    ~MyException() throw(){}    const char * what() const throw() {        return info.data();    }private:    std::string info;};#endif#ifndef BALANCE_HPP#define BALANCE_HPP#include "linkStack.hpp"class Balance{public:    enum elemType{OPAREN,CPAREN,OTHER,EOL};    Balance(const char* ex);    ~Balance(){}    bool balance();private:    LinkStack<char> _stack;    const char * _ex;    elemType getToken();};inlineBalance::Balance(const char *ex) : _ex(ex){}bool Balance::balance(){    elemType t = getToken();    while (t != EOL) {        switch (t) {        case OPAREN:            _stack.push('(');            break;        case CPAREN:            if (_stack.isEmpty()) {                return false;            } else {                _stack.pop();            }            break;        default:            break;        }        t = getToken();    }    return _stack.isEmpty(); \}Balance::elemType Balance::getToken(){    elemType re;    while(*_ex == ' ') ++_ex;    if (*_ex >= '0' && *_ex <= '9') {        while(*_ex >= '0' && *_ex <= '9') {            ++_ex;        }        return OTHER;    }    switch (*_ex++) {    case '(':        re = OPAREN;        break;    case ')':        re = CPAREN;        break;    case '\0':        re = EOL;        break;    default:        re = OTHER;        break;    }    return re;}#endif // BALANCE_HPP#ifndef CALCULATOR_HPP#define CALCULATOR_HPP#include "balance.hpp"#include "exceptions.hpp"template <typename T>class Calculator{public:    /**     * @brief The elemType enum     * 數字 加 減 乘 除 開括弧open  閉括弧close 結束標識     */    enum elemType{DATA, ADD, SUB, MULIT, DIV, OPAREN, CPAREN, EOL};    Calculator(char *ex);    ~Calculator() {        destroy(root);    }    T result();private:    struct node {        elemType type;        T data;        node *lc, *rc;        node(elemType _type, T _data, node *_lc = 0, node *_rc = 0):            type(_type),            data(_data),            lc(_lc),            rc(_rc) {        }    };    node *create(char *&ex);    elemType getToken(char *&ex, T &value);    void destroy(node *r);    T result(node *r);    node *root;};template <typename T>Calculator<T>::Calculator(char *ex){    Balance b(ex);    if (!b.balance()) {        throw MyException("() not match!!!");    }    root = create(ex);}template <typename T>void Calculator<T>::destroy(node *r){    if (r != NULL) {        destroy(r->lc);        destroy(r->rc);        delete r;    }}template <typename T>typename Calculator<T>::node* Calculator<T>::create(char *&ex){    node* p, *root = 0;    elemType reType;    T value;    while(*ex) {        reType = getToken(ex,value);        switch (reType) {        case DATA:        case OPAREN:            if(reType == DATA) {                p = new node(DATA,value);            } else {                /**                  解決這樣情況                  (4-2)*5                  樹形結構為                    |------|                         |------|                    | _ |        *                 | _ |                    |------|    --------------->          |------|     (X)                     |    \                        |    \                     |     \                       |     \                  |------|    |-----|                   |------|    |-----|                  | 4 |     |   2 |                | 4 |     |   * |                  |------|    |-----|                  |------|    |-----|                                                          |     \                                                          |      \                                                       |------|   |------|                                                       |2  |     |  5  |                                                      |------|      |------|                  ***/                p = create(ex);                node *q = new node(DATA,result(p));                destroy(p);                p = q;            }            if (root == NULL) {                root = p;            } else {                if (root->rc == NULL) {                    root->rc = p;                } else {                    root->rc->rc = p;                }            }            break;        case CPAREN:        case EOL:            return root;        case ADD:        case SUB:            root = new node(reType,0,root);            break;        case MULIT:        case DIV:            if (root->type == DATA || root->type == MULIT || root->type == DIV) {                root = new node(reType,0,root);            } else {                root->rc = new node(reType,0,root->rc);            }            break;        default:            return NULL;            break;        }    }    return root;}template <typename T>typename Calculator<T>::elemType Calculator<T>::getToken(char *&ex, T &value){    char t;    while(*ex == ' ') ++ex;    if (*ex >= '0' && *ex <= '9') {        value = 0;        while(*ex >= '0' && *ex <= '9') {            value = value*10 + *ex - '0';            ++ex;        }        return DATA;    }    if (*ex == '\0') return EOL;    t = *ex;    ++ex;    switch (t) {    case '+':        return ADD;    case '-':        return SUB;    case '*':        return MULIT;    case '/':        return DIV;    case '(':        return OPAREN;    case ')':        return CPAREN;    default:        return EOL;    }}template <typename T>T Calculator<T>::result(){    return result(root);}template <typename T>T Calculator<T>::result(node *r){    elemType t = r->type;    T t2,t3;    if (t == DATA) {        return r->data;    }    t2 = result(r->lc);    t3 = result(r->rc);    switch (t) {    case ADD:        r->data = t2 + t3;        break;    case SUB:        r->data = t2 - t3;        break;    case MULIT:        r->data = t2 * t3;        break;    case DIV:        r->data = t2 / t3;        break;    default:        break;    }    return r->data;}#endif // CALCULATOR_HPPint main(){    try {        Calculator<int> ex("(4-2)*(10+(4+6)/2)+2");        std::cout << ex.result();    } catch(std::exception &ex) {        std::cout << ex.what() << std::endl;    }    return 0;}

修複一個bug,可以處理小數,不過不進行檢錯

template <typename T>typename Calculator<T>::elemType Calculator<T>::getToken(char *&ex, T &value){    char t;    while(*ex == ' ') ++ex;    if (*ex >= '0' && *ex <= '9') {        value = 0;        T t = 0;        T t2 = 1;        bool f = false;//標識小數點        while((*ex >= '0' && *ex <= '9') || *ex == '.' ) {            if (*ex == '.') {                f = true;                ++ex;                continue;            }            if (!f) {                value = value*10 + *ex - '0';            } else {                t2 *= 0.1;                t = t + (*ex - '0')*t2;            }                        ++ex;        }        value += t;        return DATA;    }        if (*ex == '\0') return EOL;    t = *ex;    ++ex;    switch (t) {    case '+':        return ADD;    case '-':        return SUB;    case '*':        return MULIT;    case '/':        return DIV;    case '(':        return OPAREN;    case ')':        return CPAREN;    default:        return EOL;    }    }

修複bug

Balance::elemType Balance::getToken(){    elemType re;    while(*_ex == ' ') ++_ex;    //這段代碼注釋掉沒有影響,但是會增加函數的調用,效能會受影響    if (*_ex >= '0' && *_ex <= '9') {        while((*_ex >= '0' && *_ex <= '9') || *_ex == '.') {            ++_ex;        }        return OTHER;    }    switch (*_ex++) {    case '(':        re = OPAREN;        break;    case ')':        re = CPAREN;        break;    case '\0':        re = EOL;        break;    default://這邊處理所有的不是‘(’‘)’‘\0’的情況,不過函數會返回字串長度+1次        re = OTHER;        break;    }    return re;}template <typename T>Calculator<T>::Calculator(char *ex) : root(0), _ex(ex){    //    Balance b(ex);    //    if (!b.balance()) {    //        throw MyException("() not match!!!");    //    }    //在建構函式中爆出異常回導致解構函式不能調用    //    root = create(ex);}template <typename T>T Calculator<T>::result(){    Balance b(_ex);    if (!b.balance()) {        throw MyException("() not match!!!");    }    root = create(_ex);    return result(root);}

_ex為添加的資料成員

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.