我有一个像下面这样的表达。MIN(MAX(AVG(AVG(4,2),2,3),SUM(1,2))) 我已经实现了调车场算法来将中缀转换为反向波兰符号。我用两个参数添加了函数 MAX 、 MIN 和 AVG 。但是假设如果我想实现可变参数,那么我必须知道每个函数在中缀表达式中有多少个参数。有人可以告诉我如何修改调车场算法以包含否。将中缀转换为 rpn 时每个函数的参数?
4 回答
所以如果你有log max(1, 2, 3, 4, 5)
你会做:
log => push log to stack
max => push max to stack
( => push ( to stack
1 => push 1 to stack
, => pop top of stack to output => pop 1 to output
2 => push 2 to stack
, => pop 2 to output
...
=> end result: 1 2 3 4 5 max log
问题是您不知道有多少个参数属于max
以及有多少log
个(对数可能也可能不将底数作为参数)。
使用维基百科描述,应该可以计算每个函数参数分隔符(逗号):如果你有k
函数分隔符,那么你就有k + 1
参数,所以你可以输出1 2 3 4 5 max_5 log
上面的。在嵌套函数的情况下要注意不同的计数:
max(1, 2, log(3, 4), 5) => 1 2 3 4 log_2 5 max_4
---------
max has 4 arguments after evaluating log_2(3, 4)
您对max
令牌有一个计数,对log
函数有另一个计数。您需要跟踪堆栈中最顶层函数标记的计数,以及堆栈中所有其他函数标记的计数,因为您最终可能会恢复这些计数。
这就是我最终的做法。当令牌是一个左括号时,我将它添加到输出队列中。然后,当转换或执行 RPN 输出时,我遇到一个函数调用标记,我从堆栈中弹出项目,直到遇到一个开括号,丢弃它,并将其间的所有内容视为函数的参数。
可能不是一个简洁的解决方案,但就像一个魅力:)
我不确定我是否会将左括号推送到输出堆栈。这意味着您将为诸如 3 * ( 4 + 5 ) 之类的操作添加括号。相反,我将拥有与函数相关联的逻辑:当您遇到 MAX 或 MIN 时,然后将标记令牌(例如...“|”)推送到堆栈。现在,当您进行评估时,您可以使用堆栈中的所有项目,直到第一个“|” 作为函数的参数。
一个稍微整洁的解决方案是制作另一个堆栈。在找到一个开放括号时将当前令牌位置推入此堆栈。然后当找到一个封闭的括号时,弹出第一个值并使用当前标记位置之间的差异来查找括号之间的参数总数。如果运算符是函数,则可以使用该值,或者以其他方式丢弃它。