我有一个关于解析树的问题:
我有一个字符串(math expresion estring),例如:(a+b)*c-(d-e)*f/g.我必须在树中解析该表达式:
class Exp{};
class Term: public Exp{
int n_;
}
class Node: Public Exp{
Exp* loperator_;
Exp* roperator_;
char operation; // +, -, *, /
}
Run Code Online (Sandbox Code Playgroud)
我可以用什么算法来构建一个代表上面表达式字符串的树?
(a+b)*c-(d-e)*f/g 是一个固定的表达式.
要轻松创建树,请先将其转换为前缀表达式.
从示例中,前缀(A * B) + (C / D)为+ (* A B) (/ C D)
(+)
/ \
/ \
(*) (/)
/ \ / \
A B C D
((A*B)+(C/D))
Run Code Online (Sandbox Code Playgroud)
然后,您的树看起来有+作为其根节点.您可以继续填充左右子树,关于每个运算符.
此外,此链接详细解释了递归下降解析,并且可以实现.
第一步是为您的表达式编写语法。对于这种简单情况,第二步是编写递归下降解析器,这是我推荐的算法。这是递归下降解析器的 wiki 页面,它有一个漂亮的 C 实现。
http://en.wikipedia.org/wiki/Recursive_descent_parser
#include <algorithm>
#include <iostream>
#include <string>
#include <cctype>
#include <iterator>
using namespace std;
class Exp{
public:
// Exp(){}
virtual void print(){}
virtual void release(){}
};
class Term: public Exp {
string val;
public:
Term(string v):val(v){}
void print(){
cout << ' ' << val << ' ';
}
void release(){}
};
class Node: public Exp{
Exp *l_exp;
Exp *r_exp;
char op; // +, -, *, /
public:
Node(char op, Exp* left, Exp* right):op(op),l_exp(left), r_exp(right){}
~Node(){
}
void print(){
cout << '(' << op << ' ';
l_exp->print();
r_exp->print();
cout << ')';
}
void release(){
l_exp->release();
r_exp->release();
delete l_exp;
delete r_exp;
}
};
Exp* strToExp(string &str){
int level = 0;//inside parentheses check
//case + or -
//most right '+' or '-' (but not inside '()') search and split
for(int i=str.size()-1;i>=0;--i){
char c = str[i];
if(c == ')'){
++level;
continue;
}
if(c == '('){
--level;
continue;
}
if(level>0) continue;
if((c == '+' || c == '-') && i!=0 ){//if i==0 then s[0] is sign
string left(str.substr(0,i));
string right(str.substr(i+1));
return new Node(c, strToExp(left), strToExp(right));
}
}
//case * or /
//most right '*' or '/' (but not inside '()') search and split
for(int i=str.size()-1;i>=0;--i){
char c = str[i];
if(c == ')'){
++level;
continue;
}
if(c == '('){
--level;
continue;
}
if(level>0) continue;
if(c == '*' || c == '/'){
string left(str.substr(0,i));
string right(str.substr(i+1));
return new Node(c, strToExp(left), strToExp(right));
}
}
if(str[0]=='('){
//case ()
//pull out inside and to strToExp
for(int i=0;i<str.size();++i){
if(str[i]=='('){
++level;
continue;
}
if(str[i]==')'){
--level;
if(level==0){
string exp(str.substr(1, i-1));
return strToExp(exp);
}
continue;
}
}
} else
//case value
return new Term(str);
cerr << "Error:never execute point" << endl;
return NULL;//never
}
int main(){
string exp(" ( a + b ) * c - ( d - e ) * f / g");
//remove space character
exp.erase(remove_if(exp.begin(), exp.end(), ::isspace), exp.end());
Exp *tree = strToExp(exp);
tree->print();
tree->release();
delete tree;
}
//output:(- (* (+ a b ) c )(/ (* (- d e ) f ) g ))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
41458 次 |
| 最近记录: |