java华为lisp算法_华为笔试,语法树,用单行的类LISP语法字符串表示

有数字(0~9构成的正整数)、三种操作运算符(加法+、乘法*、自增^)、分隔符一个空格、左右括号

表达式形式是“(运算符 参数)”形式

比如(+ 3 4),求值结果7;(+ (* 2 3)(^4))求值结果11

语法树结束后,后面加任何字符都是合法的,比如(+ (* 2 3)(^4)))))))#$是合法的

匆匆忙忙地写了一个,感觉太长了。。。应该有很大的优化空间。

主要思路:用一个var类保存操作数,包括操作符和数字(存在联合体中,用一个枚举变量表示类型),然后遍历输入的字符串,将左括号、数字、操作符压入计算栈,当遇到右括号时,弹出数字和操作符进行计算,并弹出左括号,将结果压入。如果压入结果之后,计算栈大小为1,说明语法树结束啦,直接跳出。中间任何操作失败,都跳出输出-1,主要是这个的判断占了很大篇幅,得想办法优化。

#include

#include

#include

#include

using namespace std;

struct var {

union {

int num;

char op;

};

enum class type {ch,number} ty;

var(int n, type t=type::number) :num(n), ty(t) {}

var(char c, type t= type::ch) :op(c), ty(t) {}

};

using vtype = var::type;

unordered_set ops = { '+','*','^' };

int main() {

string exp;

while (getline(cin,exp)) {

stack cal;

bool valid =true;

for (auto i = exp.cbegin(); i != exp.cend() && valid;++i) {

if (*i >= '0' && *i <= '9') {//数字

int num = *i++ - '0';

while (i!=exp.cend() &&*i >= '0' && *i <= '9') {

num = num * 10 + *i++ - '0';

}

if (i == exp.cend()) {

valid = false;

break;

}

else

cal.emplace(num);

}

if (*i == '(' || ops.find(*i) != ops.end())//左括号或者操作符

cal.emplace(*i);

else if (*i == ')') {//有右括号就弹出东西来计算,如果不对就是不合法的

bool dual;

if (cal.empty() || cal.top().ty != vtype::number) {

valid = false;

break;

}

int rhs = cal.top().num;

int lhs;

int res;

cal.pop();

if (cal.empty()) {

valid = false;

break;

}

if (cal.top().ty == vtype::number) {

dual = true;

lhs = cal.top().num;

cal.pop();

} else if (cal.top().op == '^') {

cal.pop();

res = ++rhs;

dual = false;

} else {

valid = false;

}

if (dual) {

if (!cal.empty() && cal.top().ty == vtype::ch) {

char op = cal.top().op;

cal.pop();

if (op == '+')res = lhs + rhs;

else res = lhs * rhs;

} else {

valid = false;

}

}

if (!cal.empty() && cal.top().ty == vtype::ch && cal.top().op == '(') {

cal.pop();

cal.emplace(res);

} else {

valid = false;

}

if (cal.size() == 1 && cal.top().ty == vtype::number)break;//语法树结束

} else if (*i == ' ')continue;

else {

if (cal.size() == 1 && cal.top().ty == vtype::number)//非法字符,但是语法树已结束

break;

else valid = false;

}

}

if (valid && cal.size() == 1 && cal.top().ty == vtype::number) {

cout << cal.top().num << endl;

}

else cout << -1<

}

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值