中缀表达式建立表达式二叉树

直接建立需要分析优先级,括号在最底层,+-比*/深度低。
这里直接采用之前的代码,先将中缀表达式转化为后缀表达式。后缀表达式直接建立表达式二叉树。
利用栈即可。
中缀转后缀
栈内保存树的指针。
每读入一个字符,都建立一个节点并把地址压入栈,遇到运算符就弹出栈顶两个节点,建立一个新的树并将树根地址压入栈。

如ab*-(c-d)/e+f

实现代码:

d_tnodel.h

#ifndef TREE_LIBRARY_FUNCTIONS
#define TREE_LIBRARY_FUNCTIONS

#include <iostream>
#include <strstream>
#include <iomanip>
#include <string>
#include <queue>

#ifndef NULL
#include <cstddef>
#endif  // NULL

#include "d_tnode.h"        // use tnode class

using namespace std;

// objects hold a formatted label string and the level,column
// coordinates for a shadow tree node
class tnodeShadow
{
    public:
        string nodeValueStr;    // formatted node value
        int level,column;
        tnodeShadow *left, *right;

        tnodeShadow ()
        {}
};

// create one of three binary trees with character data.
// the argument n selects from tree 0 - tree 2
tnode<char> *buildTree(int n);

// inorder recursive output of the nodes in a binary tree.
// output separator after each node value. default value
// of separator is "  "
//template <typename T>
//void inorderOutput(tnode<T> *t, const string& separator = "  ");


// postorder recursive output of the nodes in a binary tree.
// output separator after each node value. default value
// of separator is "  "
//template <typename T>
//void postorderOutput(tnode<T> *t, const string& separator = "  ");

// traverse the tree level by level and output each node in a
// binary tree. output separator after each node value. default value
// of separator is "  "
//template <typename T>
//void levelorderOutput(tnode<T> *t, const string& separator = "  ");

// accumulate the number of leaf nodes in count
template <typename T>
void countLeaf(tnode<T> *t, int& count);

// return the depth of the binary tree
template <typename T>
int depth (tnode<T> *t);

// create copy of tree t and return a pointer to the new root
template <typename T>
tnode<T> *copyTree(tnode<T> *t);

// traverse the nodes in the binary tree and delete each node
template <typename T>
void deleteTree(tnode<T> *t);

// delete all tree nodes using deleteTree() and then assign
// t to be NULL
template <typename T>
void clearTree(tnode<T> * & t);

// recursive inorder scan used to build the shadow tree
template <typename T>
tnodeShadow *buildShadowTree(tnode<T> *t, int level, int& column);

// display a binary tree. output of a node value requires
// no more than maxCharacters
template <typename T>
void displayTree(tnode<T> *t, int maxCharacters);

// delete the nodes in the shadow tree
void deleteShadowTree(tnodeShadow *t);

tnode<char> *buildTree(int n)
{
    // 9 tnode pointers; points to the 9 items in the tree
    tnode<char> *root, *b, *c, *d, *e, *f, *g, *h, *i;

    // parameter n specifies a tree in the range 0 - 2
    switch(n)
    {
        // nodes d and e are leaf nodes
        case 0:
            d = new tnode<char> ('D');
            e = new tnode<char> ('E');
            b = new tnode<char> ('B',(tnode<char> *)NULL, d);
            c = new tnode<char> ('C',e, (tnode<char> *)NULL);
            root = new tnode<char> ('A',b, c);
            break;

        // nodes g, h, i, and d are leaf nodes
        case 1:
            g = new tnode<char> ('G');
            h = new tnode<char> ('H');
            i = new tnode<char> ('I');
            d = new tnode<char> ('D');
            e = new tnode<char> ('E',g, (tnode<char> *)NULL);
            f = new tnode<char> ('F',h, i);
            b = new tnode<char> ('B',d, e);
            c = new tnode<char> ('C',(tnode<char> *)NULL, f);
            root = new tnode<char> ('A',b, c);
            break;

        // nodes g, h, i and f are leaf nodes
        case 2:
            g = new tnode<char> ('G');
            h = new tnode<char> ('H');
            i = new tnode<char> ('I');
            d = new tnode<char> ('D',(tnode<char> *)NULL, g);
            e = new tnode<char> ('E',h, i);
            f = new tnode<char> ('F');
            b = new tnode<char> ('B',d, (tnode<char> *)NULL);
            c = new tnode<char> ('C',e, f);
            root = new tnode<char> ('A',b, c);
            break;
    }

    return root;
}

template <typename T>
void inorderOutput(tnode<T> *t, const string& separator = "  ")
{
   // the recursive scan terminates on a empty subtree
   if (t != NULL)
   {
      inorderOutput(t->left, separator);    // descend left
      cout << t->nodeValue << separator;    // output the node
      inorderOutput(t->right, separator);   // descend right
   }
}

template <typename T>
void postorderOutput(tnode<T> *t, const string& separator = "  ")
{
   // the recursive scan terminates on a empty subtree
   if (t != NULL)
   {
      postorderOutput(t->left, separator);  // descend left
      postorderOutput(t->right, separator); // descend right
      cout << t->nodeValue << separator;            // output the node
   }
}

template <typename T>
void levelorderOutput(tnode<T> *t, const string& separator = "  ")
{
   // store siblings of each node in a queue so that they are
   // visited in order at the next level of the tree
   queue<tnode<T> *> q;
   tnode<T> *p;

   // initialize the queue by inserting the root in the queue
   q.push(t);

   // continue the iterative process until the queue is empty
   while(!q.empty())
   {
      // delete front node from queue and output the node value
      p = q.front();
        q.pop();
      cout << p->nodeValue << separator;

        // if a left child exists, insert it in the queue
      if(p->left != NULL)
            q.push(p->left);
      // if a right child exists, insert next to its sibling
      if(p->right != NULL)
            q.push(p->right);
   }
}

// assume that count initialized to 0
template <typename T>
void countLeaf (tnode<T> *t, int& count)
{
   if (t != NULL)
   {
      // check if t is a leaf node (no children).
      // if so, increment count
      if (t->left == NULL && t->right == NULL)
         count++;

        countLeaf(t->left, count);      // descend left
        countLeaf(t->right, count); // descend right
   }
}

// determine the depth of the tree using a postorder scan
template <typename T>
int depth (tnode<T> *t)
{
   int depthLeft, depthRight, depthval;

   if (t == NULL)
        // depth of an empty tree is -1
      depthval = -1;
   else
    {
        // find the depth of the left subtree of t
        depthLeft= depth(t->left);
        // find the depth of the right subtree of t
        depthRight= depth(t->right);
        // depth of the tree with root t is 1 + maximum
        // of the depths of the two subtrees
        depthval = 1 +
            (depthLeft > depthRight ? depthLeft : depthRight);
   }

    return depthval;
}

template <typename T>
tnode<T> *copyTree(tnode<T> *t)
{
   // newNode points at a new node that the algorithm
    // creates. newLptr. and newRptr point to the subtrees
    // of newNode
   tnode<T> *newLeft, *newRight, *newNode;

   // stop the recursive scan when we arrive at empty tree
   if (t == NULL)
      return NULL;

   // build the new tree from the bottom up by building the two
   // subtrees and then building the parent. at node t, make
    // a copy of the left subtree and assign its root node pointer
    // to newLeft. make a copy of the right subtree and assign its
    // root node pointer to newRight
    newLeft = copyTree(t->left);
    newRight = copyTree(t->right);

   // create a new node whose value is the same as the value in t
    // and whose children are the copied subtrees
   newNode = new tnode<T> (t->nodeValue, newLeft, newRight);

   // return a pointer to the root of the newly copied tree
   return newNode;
}

template <typename T>
void deleteTree(tnode<T> *t)
{
    // postorder scan. delete left and right
    // subtrees of t and then node t
   if (t != NULL)
   {
      deleteTree(t->left);
      deleteTree(t->right);
      delete t;
   }
}

template <typename T>
void clearTree(tnode<T> * & t)
{
    deleteTree(t);
    t = NULL;
}

template <typename T>
tnodeShadow *buildShadowTree(tnode<T> *t, int level, int& column)
{
    // pointer to new shadow tree node
    tnodeShadow *newNode = NULL;
    // text and ostr used to perform format conversion
    char text[80];
    ostrstream ostr(text,80);

    if (t != NULL)
    {
        // create the new shadow tree node
        newNode = new tnodeShadow;

        // allocate node for left child at next level in tree; attach node
        tnodeShadow *newLeft = buildShadowTree(t->left, level+1, column);
        newNode->left = newLeft;

        // initialize data members of the new node
        ostr << t->nodeValue << ends;   // format conversion
        newNode->nodeValueStr = text;
        newNode->level = level;
        newNode->column = column;

        // update column to next cell in the table
        column++;

        // allocate node for right child at next level in tree; attach node
        tnodeShadow *newRight = buildShadowTree(t->right, level+1, column);
        newNode->right = newRight;
    }

    return newNode;
}

template <typename T>
void displayTree(tnode<T> *t, int maxCharacters)
{
    string label;
    int level = 0, column = 0;
    int colWidth = maxCharacters + 1;
    //
    int currLevel = 0, currCol = 0;

    if (t == NULL)
        return;

    // build the shadow tree
    tnodeShadow *shadowRoot = buildShadowTree(t, level, column);

    // use during the level order scan of the shadow tree
    tnodeShadow *currNode;
   // store siblings of each tnodeShadow object in a queue so that
    // they are visited in order at the next level of the tree
   queue<tnodeShadow *> q;

   // insert the root in the queue and set current level to 0
   q.push(shadowRoot);

   // continue the iterative process until the queue is empty
   while(!q.empty())
   {
      // delete front node from queue and make it the current node
      currNode = q.front();
        q.pop();

        // if level changes, output a newline
        if (currNode->level > currLevel)
        {
            currLevel = currNode->level;
            currCol = 0;
            cout << endl;
        }

        // if a left child exists, insert the child in the queue
      if(currNode->left != NULL)
            q.push(currNode->left);

        // if a right child exists, insert the child in the queue
      if(currNode->right != NULL)
            q.push(currNode->right);

        // output formatted node label
        if (currNode->column > currCol)
        {
            cout << setw((currNode->column-currCol)*colWidth) << " ";
            currCol = currNode->column;
        }
        cout << setw(colWidth) << currNode->nodeValueStr;
        currCol++;
   }
    cout << endl;

    // delete the shadow tree
    deleteShadowTree(shadowRoot);
}

void deleteShadowTree(tnodeShadow *t)
{
    // if current root node is not NULL, delete its left subtree,
    // its right subtree and then the node itself
    if (t != NULL)
    {
        deleteShadowTree(t->left);
        deleteShadowTree(t->right);
        delete t;
    }
}

#endif   // TREE_LIBRARY_FUNCTIONS

d_tnode.h

#ifndef TREENODE
#define TREENODE

// represents a node in a binary tree
template <typename T>
class tnode
{
   public:
        // tnode is a class implementation structure. making the
        // data public simplifies building class functions
        T nodeValue;
        tnode<T> *left, *right;

        // default constructor. data not initialized
        tnode()
        {}

      // initialize the data members
        tnode (const T& item, tnode<T> *lptr = NULL, 
                 tnode<T> *rptr = NULL):
                    nodeValue(item), left(lptr), right(rptr)
        {}
};

#endif  // TREENODE

main.cpp

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <stack>
#include <stdlib.h>
#include <vector>
#include <sstream>
#include "d_tnodel.h"
#include "d_tnode.h"
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back

//#define LOCAL
const int MAXN =1e5+10;

template<typename T>
class postfixEval {
public:
    postfixEval();
    string getPostfixExp() const;
    void setPostfixExp(const string& postfixExp);
    T evaluate();
    stack<T> operandStack;
private:
    string postfixExpression;
    void getOperands(T& left, T& right);
    T compute(T left, T right, char op) const;
    bool isOperator(char ch) const;
    // is ch one of '+','-','*','/','%','^'
};

template<typename T>
void postfixEval<T>::getOperands(T& left, T& right) {
    if (operandStack.empty())
        throw  "postfixEval: Too many operators";
    right = operandStack.top();
    operandStack.pop();
    if (operandStack.empty())
        throw  "postfixEval: Too many operators";
    left = operandStack.top();
    operandStack.pop();
}

template<typename T>
T postfixEval<T>::compute(T left, T right, char op) const {
    T value;
    switch(op) {
    case '+':
        value = left + right;
        break;
    case '-':
        value = left - right;
        break;
    case '*':
        value = left * right;
        break;
    case '%':
        if(int(right)!=right) throw "invalid expression";
        if (right == 0) throw "postfixEval: divide by 0";
        value = int(left) % int(right)*1.0;
        break;
    case '/':
        if (right == 0)
            throw "postfixEval: divide by 0";
        value = left / right;
        break;
    case '^':
        if (left == 0 && right == 0)
            throw "postfixEval: 0^0 undefined";
        value = 1;
        while (right > 0) {
            value *= left;
            right--;
        }
        break;
    }
    return value;
}

template<typename T>
bool postfixEval<T>::isOperator(char ch) const {
    return ch == '+' || ch == '-' || ch == '*' ||
           ch == '%' || ch == '/' || ch == '^';
}

template<typename T>
postfixEval<T>::postfixEval() {}

template<typename T>
string postfixEval<T>::getPostfixExp() const {
    return postfixExpression;
}

template<typename T>
void postfixEval<T>::setPostfixExp(const string& postfixExp) {
    postfixExpression = postfixExp;
}
template<typename T>
T postfixEval<T>::evaluate() {
    T left, right, expValue;
    char ch;
    int cnt=0;
    int id[MAXN];
    string temp(postfixExpression);
    for(int i=0; i<temp.size(); i++) {
        if(isOperator(temp[i])) {
            temp[i]=' ';
            id[cnt++]=i;
        }
    }
    stringstream ss(temp);
    T x;
    vector<T> vec;
    while(ss>>x) {
        vec.pb(x);
    }
    for (int i=0,j=0,x=0; i < postfixExpression.length();) {
        while(isspace(postfixExpression[i])) i++;
        char ch=postfixExpression[i];
        if(id[j]==i) {
            getOperands(left, right);
            operandStack.push(compute(left, right, ch));
            i++;
            j++;
        } else {
            operandStack.push(vec[x++]);
            while(!isspace(temp[i])) i++;
        }
    }
    expValue = operandStack.top();
    operandStack.pop();
    if (!operandStack.empty())
        throw "postfixEval: Too many operands";
    return expValue;
}


class expressionSymbol {
public:
    expressionSymbol();
    expressionSymbol(char ch);
    friend bool operator>= (const expressionSymbol& left,
                            const expressionSymbol& right);
    char getOp() const;
private:
    char op;
    int inputPrecedence;
    int stackPrecedence;
};

expressionSymbol::expressionSymbol() {}

expressionSymbol::expressionSymbol(char ch) {
    op = ch;
    switch(op) {
    case '+':
    case '-':
        inputPrecedence = 1;
        stackPrecedence = 1;
        break;
    case '*':
    case '%':
    case '/':
        inputPrecedence = 2;
        stackPrecedence = 2;
        break;
    case '^':
        inputPrecedence = 4;
        stackPrecedence = 3;
        break;
    case '(':
        inputPrecedence = 5;
        stackPrecedence = -1;
        break;
    case ')':
        inputPrecedence = 0;
        stackPrecedence = 0;
        break;
    }
}

char expressionSymbol::getOp() const {
    return op;
}

bool operator>= (const expressionSymbol& left, const expressionSymbol& right ) {
    return left.stackPrecedence >= right.inputPrecedence;
}


class infix2Postfix {
public:
    infix2Postfix();
    infix2Postfix(const string& infixExp);
    void setInfixExp(const string& infixExp);
    string postfix();
private:
    string infixExpression;
    string postfixExpression;
    stack<expressionSymbol> operatorStack;
    void outputHigherOrEqual(const expressionSymbol& op);
    bool isOperator(char ch) const;
    //  ch is one of '+','-','*','/','%','^'
};

void infix2Postfix::outputHigherOrEqual(const expressionSymbol& op) {
    expressionSymbol op2;
    while(!operatorStack.empty() &&
            (op2 = operatorStack.top()) >= op) {
        operatorStack.pop();
        postfixExpression += op2.getOp();
        postfixExpression += ' ';
    }
}

bool infix2Postfix::isOperator(char ch) const {
    return ch == '+' || ch == '-' || ch == '*' ||
           ch == '%' || ch == '/' || ch == '^';
}

infix2Postfix::infix2Postfix() {
}

infix2Postfix::infix2Postfix(const string& infixExp):
    infixExpression(infixExp) {
}

void infix2Postfix::setInfixExp(const string& infixExp) {
    infixExpression = infixExp;
    postfixExpression = " ";
}


string infix2Postfix::postfix() {
    expressionSymbol op;
    int rank = 0;
    char ch;
    string temp(infixExpression);
    int cnt=0,id[MAXN];
    mem(id,0);
    for(int i=0; i<temp.size(); i++) {
        if(isOperator(temp[i]) || temp[i]=='(' || temp[i]==')') temp[i]=' ',id[cnt++]=i;
    }
    stringstream ss(temp);
    string x;
    vector<char> vec;
    while(ss>>x) {
        vec.pb(x[0]);
    }
    for (int i=0,j=0,x=0; i < infixExpression.length();) {
        ch = infixExpression[i];
        if(isspace(ch)) {
            i++;
        } else  {
            if (i!=id[j]) {
                stringstream s;
                string aa;
                s<<vec[x++];
                s>>aa;
                postfixExpression += aa;
                while(!isspace(infixExpression[i]) && i<infixExpression.length()) i++;
                postfixExpression += ' ';
                rank++;
                if (rank > 1)
                    throw "infix2Postfix: Operator expected";
            } else {
                j++;
                if (isOperator(ch) || ch == '(') {
                    if (ch != '(')  rank--;
                    if (rank < 0)
                        throw "infix2Postfix: Operand expected";
                    else {
                        op = expressionSymbol(ch);
                        outputHigherOrEqual(op);
                        operatorStack.push(op);
                    }
                    i++;
                } else if (ch == ')') {
                    op = expressionSymbol(ch);
                    outputHigherOrEqual(op);
                    if(operatorStack.empty())
                        throw "infix2Postfix: Missing '('";
                    else
                        operatorStack.pop();
                    i++;
                } else if (!isspace(ch)) {
                    throw "infix2Postfix: Invalid input";
                    i++;
                }
            }
        }
    }
    if (rank != 1)
        throw "infix2Postfix: Operand expected";

    else {
        while (!operatorStack.empty()) {
            op = operatorStack.top();
            operatorStack.pop();
            if (op.getOp() == '(')
                throw "infix2Postfix: Missing ')'";
            else {
                postfixExpression += op.getOp();
                postfixExpression += ' ';
            }
        }
    }
    return postfixExpression;
}
void simple(string &s){
    string t(s);
    s="";
    for(int i=0;i<t.size();i++){
        if(t[i]==' '||t[i]=='('||t[i]==')') continue;
        else s+=t[i];
    }
}
bool check(char x){return x=='*'||x=='/'||x=='+'||x=='-';}
int main() {
    //中缀转后缀
    string in_order="a * b + ( c - d ) / e - f ";
    infix2Postfix a;
    a.setInfixExp(in_order);
    string post_order=a.postfix();
    //将后缀的空格去掉
    simple(post_order);
    int n=post_order.size();
    cout<<post_order<<endl;
    //建树
    stack<tnode<char>* > st;
    for(int i=0;i<n;i++){
        tnode<char> *x=new tnode<char>(post_order[i]);
        if(check(post_order[i])){
            tnode<char> *a=new tnode<char>(st.top()->nodeValue);a->left=st.top()->left,a->right=st.top()->right;st.pop();
            tnode<char> *b=new tnode<char>(st.top()->nodeValue);b->left=st.top()->left,b->right=st.top()->right;st.pop();
            x->left=b;
            x->right=a;
        }
        st.push(x);
    }
    tnode<char> *t=st.top();
    displayTree(t,1);
    return 0;
}

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值