问题
There are many algorithms to convert infix to postfix all over the web. But my question is how to make that to support functions? For example sin(x+y)*z.
I will appreciate a code.
回答1:
If you are looking for an algorithm that gives you the conversion infix to postfix including function call support, you can use the below pseudocode(which looks like python code). I have written this for my case but not yet tested thouroughly. If you find any bugs please let me know.
I have also written a Java implementation for the same.
Also, there are few things to note about this implementation:
This algorithm assumes a stream of tokens in infix. It does not parse a expression string. So each token can be identified as an operand, operator, function call etc.
There are 7 different kinds of tokens:
- Operands X, Y etc
- Left Paranthesis - (
- Right Paranthesis - )
- Operators - +, *
- Function call starts - sin(
- Function call ends - sin( x )
- Comma - ,
Function call starts are denoted by
[
character in the algorithm and function call ends are denoted by]
. Please note that function call termination is a different token than Right Paranthesis)
although they may be represented by the same character in the string expression.Every operator is a binary operator with precedence and associativity as their usual meaning.
Comma
,
is a special binary operator with precedence ofNEGATIVE INFINITY
and associativity as LEFT (same as + and *). Comma operator is used to separate the arguments of a function call. So for a function call:f(a,b,c) first comma separates a and b second comma separates a,b and c So the postfix for the above will be ab,c,f
You can view Comma operator as a add to list function which adds the second argument to the list specified by the first argument or if both are single values it creates a list of two values.
Algorithm
infix_to_postfix(infix):
postfix = []
infix.add(')')
stack = []
stack.push('(')
for each token in infix:
if token is operand:
postfix.add(token)
if token is '[':
stack.push(token)
else if token is operator:
if stack is empty OR
stack[top] is '(' or stack[top] is '[':
stack.push(token)
else if (operator)token['precedence'] > stack[top]['precedence'] OR
( (operator)token['precedence'] == stack[top]['precedence'] AND
(operator)token['associativity') == 'RIGHT' ):
stack.push(token)
else
postfix.add(stack.pop())
stack.push(token)
else if token is '(':
stack.push(token)
else if token is ')':
while topToken = stack.pop() NOT '(':
postfix.add(topToken)
else if token is ']':
while True:
topToken = stack.pop()
postfix.add(topToken)
if topToken is '[':
break
else if token is ',':
while topToken = stack.peek() NOT '[':
postfix.add(topToken)
stack.pop()
stack.push(token)
回答2:
Thats quite easy: It work with functions too, the regular operators you use (like +,-,*) are functions too. Your problem is, that what you consider "function" (like sin) is not in infix, but they are in prefix.
To come back to your problem: Just convert these prefix functions into postfix (you should find prefix to postfix on the web too - my assumption is that you dont know the "prefix" term) beforehand.
EDIT: Basicaly it is nothing more that first convert the arguments and output them in sequence and append the name of the function afterwards.
回答3:
The code you'll have to work out yourself. Using your specific case as an example might help get you started; the postfix form of sin(x + y) * z
would be:
x y + sin z *
Note that in this one example some operations operation on two values (+
and *
), and others one (sin
)
回答4:
binary operators like +
can be considered as +(x,y)
Similarly Consider sin, cos, etc functions as unary operators. So, sin(x+y)*z can be written as x y + sin z *
. You need to give these unary functions special treatment.
来源:https://stackoverflow.com/questions/11708195/infix-to-postfix-with-function-support