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