中缀表达式求值问题

51 篇文章 1 订阅
2 篇文章 0 订阅

1)有无括号

2)一种优先级运算符(只有+-或*/) 还是2种(+- 和*/都有)

3) 求逆波兰序列,求值,求表达式树


两种思路

1.分治 (求值,和求表达式树都可以用)nlogn

1)先去掉冗余括号(两边最外面的,如(1), (1 + 2) ),如果有的话。找到优先级最小的运算符的位置p,如果不存在,说明是一个数字,返回atoi后的值

2)两边递归求值 

3)对两边的值应用该运算符,返回结果。

对于找最小运算符:在括号内的不考虑,因为其优先级更高,同一优先级的运算符,前面的优先级高,后面的低。

map<char, function<int(int, int)>> = {{'+', [](int a, int b) {return a + b;}}, {'-', [](int a, int b) {return a - b;}}};

int eval(string &s, int l, int r) {
    for (; l < r && s[l] == '( && s[r] == ')'; ++l, --r ) ;
    int p = findLowestOp(s, l, r);
    if (p == -1) return stoi(s.substr(l, r - l + 1));
    return op[s[p]](eval(s, l, p - 1), eval(s, p + 1, r));
}

int findLowestOp(string &s, int l, int r) {
    int p = -1 , nestedLevel = 0;
    for (int i = l; i <= r; ++i) {
        if (s[i] == '(') ++nestedLevel;
        else if (s[i] == ')') --nestedLevel;
        else if (string("+-*/").find(s[i]) != string ::npos && nestedLevel == 0 && (p < 0 || s[i] == '+' || s[i] == '-' || s[p] == '*' || s[p] == '/' )) p = i;
    }
    return p;
}

2 利用单调栈 O(n)

算法主要参与者:

1)操作符函数映射表

2)操作数栈operand,操作符栈op

3)token stream (可以先用操作符split,也可以实时tokenize)


算法框架:token 流加一个结束符#,依次取token:

1)如果token是操作数,atoi, 入operand栈

2)token是操作符,while token优先级比op栈顶元素低,则取op栈顶操作符做运算,相应的操作数是operand栈的最近的两个数

对于括号,可以看作是一种分界,左括号可以看作是一个新的op栈的栈底, 右括号可以看作是括号内表达式的结束符。

def evaluateExpression(self, expression):
	m = {'+' : lambda a, b : a + b, '-' : lambda a, b : a - b, '*' : lambda a, b : a * b, '/' : lambda a, b : a / b}
	op, oprand = [], []
	for token in expression + ['#']:
		if token.isdigit(): oprand.append(int(token))
		else:
			while len(op) > 0 and token != '(' and op[-1] != '(' and  (token in '#)+-' or op[-1] in '*/'):
				b = oprand.pop();
				oprand[-1] = m[op.pop()](oprand[-1], b)
			if token == ')': op.pop()
			else: op.append(token)
	if len(oprand) > 0: return oprand[-1]
	return 0


详细解释条件判断部分:

len(op) > 0 和 op[-1]!= '(' 都是判断当前栈不为空(左括号mark一个新op栈的开始)

token != '(' 表示这不是一个“复合操作数”,括号代表一个子表达式,是值,这里比较的是运算符。

token in '#)+=' 当前运算符是这些,肯定不如栈顶运算符优先级高

op[-1] in '*/'  栈顶上已经是最高优先级的


一个逆向问题,给定一组数A,添加操作符使得表达式值为给定target

t是表达式最后一个term,

def solve(A, i, v, t, target, e):
    if i == len(A):
        if v == target: print e
    else:
        if i == 0: solve(A, i + 1, A[i], A[i], target, str(A[i]))
        else:
            solve(A, i + 1, v + A[i], A[i], target, e + '+' + str(A[i]))
            solve(A, i + 1, v - A[i], -A[i], target, e + '-' + str(A[i]))
            solve(A, i + 1, v - t + t * A[i], f * A[i], target, e + '*' + str(A[i]))
            if A[i] != 0: solve(A, i + 1, v - t + t / A[i], f / A[i], target, e + '/' + str(A[i]))



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值