Generate postfix without binary tree - algorithm

Can we generate a postfix format string from an expression without creating a binary tree or AST tree
For example, I have an expression exp = "1 + 2 * 3 * ( 4 - 2 ) + A / B "
and I want to generate a postfix string = "1 2 3 * 4 2 - * + A B / +"

Related

Stack And Arithmetic Evaluation

A stack is said to be the ideal data structure for Arithmetic Evaluation. Why is it so?
Why do we even need a data structure for Arithmetic Evaluation? I've been studying about this for some time now and still confused. I don't understand what is the use of Prefix and Postfix expressions because the Infix expression is quite readable.
Answer for the part of why postfix/prefix over infix is quite well explained here.As a summary infix is readable but not easily parsed
As for why stack is used here is:
1: push,pop in O(1) time are quite useful for evaluation.
2: push: add the operand on stack.
3: pop: remove the operand and evaluate expression(binary)
4: final result is the only one left on stack after parsing
The infix expression is readable, yes. But if you want to write an algorithm that can evaluate an arithmetic expression, how would you do?
Take the following expression:
3 + 4 * 5 + 2 ^ 3 * 12 + 6
How does your algorithm proceed from there?
A simple and naive way is to look for the highest-precedence operation, evaluate it, then rewrite the string, and keep doing that until all operations have been performed. You'd get this result:
3 + 4 * 5 + 2 ^ 3 * 12 + 6
3 + 4 * 5 + 8 * 12 + 6
3 + 20 + 96 + 6
23 + 102
125
That is one way to do it. But not a particularly efficient way. Looking through the string for the highest-precedence operation takes time linear in the length of the string, and you have to do that once per operation, and rewrite the string every time. You end up with something like a quadratic complexity. There might be a few tricks to be slightly more efficient, but it's not going to be as efficient as other existing methods.
Another possible method is to put the expression into a tree, called a "syntax tree" or "abstract syntax tree". We get this:
+
/ / \ \
3 * * 6
/ \ / \
4 5 ^ 12
/ \
2 3
This tree is easier to evaluate for an algorithm, compared to the expression we had before: it is a linked structure, in which you can easily replace one branch by the value of that branch without having to rewrite everything else in the tree. So you replace 2^3 with 8 in the tree, then 8 * 12 with 96, etc.
Postfix (or prefix) notation is harder to read for humans, but much easier to manipulate for an algorithm. My previous example becomes this in postfix:
3 4 5 * + 2 3 ^ 12 * + 6 +
This can be evaluated easily reading it from left to right; every time you encounter a number, push it onto a stack; every time you encounter an operator, pop the two numbers on top of the stack, perform the operation, and push the result.
Assuming the postfix expression was correct, there should be a single number in the stack at the end of the evaluation.
EXPR | [3] 4 5 * + 2 3 ^ 12 * + 6 +
STACK | 3
EXPR | 3 [4] 5 * + 2 3 ^ 12 * + 6 +
STACK | 3 4
EXPR | 3 4 [5] * + 2 3 ^ 12 * + 6 +
STACK | 3 4 5
EXPR | 3 4 5 [*] + 2 3 ^ 12 * + 6 +
STACK | 3 20
EXPR | 3 4 5 * [+] 2 3 ^ 12 * + 6 +
STACK | 23
EXPR | 3 4 5 * + [2] 3 ^ 12 * + 6 +
STACK | 23 2
EXPR | 3 4 5 * + 2 [3] ^ 12 * + 6 +
STACK | 23 2 3
EXPR | 3 4 5 * + 2 3 [^] 12 * + 6 +
STACK | 23 8
EXPR | 3 4 5 * + 2 3 ^ [12] * + 6 +
STACK | 23 8 12
EXPR | 3 4 5 * + 2 3 ^ 12 [*] + 6 +
STACK | 23 96
EXPR | 3 4 5 * + 2 3 ^ 12 * [+] 6 +
STACK | 119
EXPR | 3 4 5 * + 2 3 ^ 12 * + [6] +
STACK | 119 6
EXPR | 3 4 5 * + 2 3 ^ 12 * + 6 [+]
STACK | 125
And there we have the result. We only had to read through the expression once. Thus the execution time is linear. This is much better than the quadratic execution time we had when trying to evaluate the infix expression directly and had to read through it several time, looking for the next operation to perform.
Note that converting from infix to postfix can also be done in linear time, using the so-called Shunting Yard algorithm, which uses two stacks. Stacks are awesome!

How to solve this in an efficient way with optimum time complexity?

Given a set of N numbers in an array. Given Q queries. Each Query contains 1 number x.
For each query, you need to add x to each element of the array and then report the sum of absolute values in the array.
Note : Changes to the array are permanent. See Sample for more clarification.
Input Format
First line contains N , number of elements in the array.
Next line contains N space separated integers of the array.
Next line contains Q(number of queries).
Next line contains Q space separated integers(the number x).
Output Format
For each query , output the sum in a newline.
Constraints
1 ≤ N ≤ 500000
1 ≤ Q ≤ 500000
-2000 ≤ number in each Query ≤ 2000
-2000 ≤ value of the array element ≤ 2000
Sample Input
3
-1 2 -3
3
1 -2 3
Sample Output
5
7
6
Explanation
After Query 1 : [ 0 , 3 , -2 ] => sum = 0 + 3 + 2 = 5
After Query 2 : [ -2 , 1 , -4 ] => sum = 2 + 1 + 4 = 7
After Query 3 : [ 1 , 4 , -1 ] => sum = 1 + 4 + 1 = 6
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,*a,q,*aq;
long int sum=0;
scanf("%d",&n);
a=(int*)malloc(sizeof(int)*n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
scanf("%d",&q);
aq=(int*)malloc(sizeof(int)*q);
for(int i=0;i<n;i++)
scanf("%d",&aq[i]);
for(int i=0;i<q;i++)
{
for(int j=0;j<n;j++)
{
sum+=abs(aq[i]+a[j]);
a[j]=aq[i]+a[j];
}
printf("%ld\n",sum);
sum=0;
}
}
Some test cases are timing out.
Your solution is performing N.Q operations, which is huge.
First notice that the range of the data is moderate, so that you can represent the N numbers using an histogram of 4001 entries. This histogram is computed in N operations (plus initializing the bins).
Then the requested sum is obtained as the sum of the absolute differences with every bin, weighted by the bin values. This lowers the workload from N.Q to B.Q (B is the number of bins).
If I am right, we can do much better by decomposing the sum in a subsum for the negative values and another in the positives. And these sums are obtained by computing prefix sums. This should lead to a solution in Q operations, after preprocessing the histogram in B operations.
Here's an outline of an algorithm:
Sample Input
3
-1 2 -3
Sort the data and compute prefix sums:
-3, -1, 2
-3, -4, -2 (prefix sums)
(Using a histogram as Yves Daoust suggested would eliminate the initial sort and any binary search to find the three sections below, which would significantly optimise complexity.)
Maintain a running delta:
delta = 0
For each query of
1 -2 3
Query 1:
* update delta:
delta = 0 + 1 = 1
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(2 * 1 + (-4 - 0)) + abs(1 * 1 + (-2 -(-4)))
= abs(2 - 4) + abs(1 + 2)
= 5
Query -2:
* update delta:
delta = 1 - 2 = -1
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(2 * (-1) + (-4 - 0)) + abs(1 * (-1) + (-2 -(-4)))
= abs(-2 - 4) + abs(-1 + 2)
= 7
Query 3:
* update delta:
delta = -1 + 3 = 2
* identify three sections:
[negative unaffected] [switches sign] [positive unaffected]
-3, -1, 2
* Add for each section abs(num_elements * delta + prefix_sum):
abs(1 * 2 + (-3 - 0)) + abs(1 * 2 + (-4 - (-3))) + abs(1 * 2 + (-2 -(-4)))
= abs(2 - 3) + abs(2 - 1) + abs(2 + 2)
= 6
Sample Output
5
7
6

converting Infix to prefix conversion

Recently I have went through some sites,
for converting the Infix to Prefix notation and finally got tucked up.
I have given the steps which I have done..
Ex:- (1+(2*3)) + (5*6) + (7/8)
Method 1:- (Manual Conversion without any algorithm):-
Step1: (1+(*23)) + (*56) + (/78)
Step2: (+1*23) + (*56) + (/78)
Step3: +(+1*23)(*56) + (/78)
Step4: +[+(+1*23)(*56)](/78)
Step5: +++1*23*56/78 **--- Final Ans -----**
Method 2:-
As per the site http://scanftree.com/Data_Structure/infix-to-prefix
Step1: Reverse it:-
) 8 / 7 ( + ) 6 * 5 ( + ) ) 3 * 2 ( + 1 (
Step2: Replace the '(' by ')' and vice versa:
( 8 / 7 ) + ( 6 * 5 ) + ( ( 3 * 2 ) + 1 )
Step3: Convert the expression to postfix form:-
8 7 / 6 5 * + 3 2 * 1 + +
Step4: Reverse it
+ + 1 * 2 3 + * 5 6 / 7 8 --- Final Ans -----
So, here I got totally hanged.
Could any one please provide some light on following things:-
On where I went wrong in the above 2 methods
Which is the right answer
so I can able to understand the concept more better.
Your method is not correct, look at the comment, it says that ( a + b ) + c = a + ( b + c ) . What about (a + b) * c? (a + b) * c != a + (b * c).
According to your manual algorithm, you put the last + is placed to the front. It is not correct. If you use * instead of last + , where did you put it ? Just think about that, then you can easily find the problem with your algorithm.
Another algorithm for solving this problem is just parenthesis it before proceeding. Replace every left parenthesis with the operator inside it.
Example, ((1+(2*3)) + ((5*6) + (7/8))) then it become ++1*23+*56+/78. Your algorithm is correct if the precedence of the operator inside is same. If it is not it will fail.
NOTE : Your answer can also be obtained by the arrangement of parenthesis. (((1+(2*3)) + (5*6)) + (7/8)) then it becomes +++1*23*56/78. But if the last one is * instead of + then it doesn't work.
(b * b - 4 * a * c ) / (2 * c) EQUATION--1;
Now I will solve this mathematically by substituting different variables, and doing 2 terms at time.
=> x=bb* ; y=4a* ; z=2c*
these above are the substitution of first time, use in eq 1
( x - y * c )/(z)
again doing the substitutions with new variables.
=> i=yc* ;
(x - i)/z
=> j=xi-;
j/z
Now this here is the base case solve it then substitute back all the variables accordingly.
jz/
Now back substitution
xi- 2c* /
bb* yc * - 2c* /
bb* 4a* c * -2a*/
The Manual conversion is correct because when we reverse the infix expression to calculate the prefix, the associativity of the expression changes from left to right to right to left which is not considered in the algorithm and often it is ignored.
Example:
expression:5-3-2 :infix to prefix(manual conversion)
(-5 3)-2
-(- 5 3) 2
- - 5 3 2
now by the algorithm(if associativity not changed)
reverse expression: 2 - 3 - 5
postfix: 2 3 - 5 -
again reverse to get prefix: - 5 - 3 2
now see if we ignored the associativity, it made a huge difference
now if we change the associativity from left to right to right to left:
then :
reverse expression: 2 - 3 - 5
postfix: 2 3 5 - - (like a^b^b to postfix: abc^^ because it is also right associative)
reverse - - 5 3 2

How to solve a simple linear equation using postfix

I have a program that takes in a simple linear equation and transforms it into its equivalent in postfix.
For example:
3x+7=4(2x-1)
would be transformed into
3 x * 7 + = 4 2 x * 1 - *
How can i get the value of x in this example using its postfix form. Any help will be greatly appreciated thank you
EDIT - I need help with the logic not the code (I'm not asking for people to do the code for me)
If your linear equation is always in the form of a right hand side (RHS) in terms of x and a left hand side (LHS) in terms of x, then the following would work.
Subtract the LHS from both the LHS and the RHS. Then you have 0 on the LHS and an expression in terms of x on the RHS.
Begin to simplify the postfix expression. Every time you encounter an addition or subtraction operation with a numerical operand, add or subtract that value from the LHS as appropriate, and replace the operand in the calculation with 0.
At the end you should be left with an equation in the form of b = a * x. The solution (if one exists and is unique) is then b / a.
Same as algebra, first let's get it into a simplified form:
3 x * 7 + = 4 2 x * 1 - *
We see a = 2 x *, then b = a 1 -, leaving 4 b *. Multiply each term in b:
3 x * 7 + = 2 4 * x * 1 4 * -
3 x * 7 + = 8 x * 4 -
Do the same on the left:
3 7 / x * 1 + = 8 x * 4 -
Now subtract 1 from each side by removing a top-level 1 + or otherwise altering some top-level addition:
3 7 / x * = 8 x * 5 -
And subtract 8 x *:
3 7 / x * 8 x * - = 0 5 -
Move things around and multiply by -1:
8 x * 3 7 / x * - = 5
Note: multiplying by -1 is easy. Algebraic notation:
(a - b) * -1 = (0 + (a - b)) * -1
(a - b) * -1 = -1*0 + (-1*a - -1*b)
(a - b) * -1 = 0 + (-a - -b)
(a - b) * -1 = (-a + b)
(a - b) * -1 = b - a
I tried using this once to fix a mistake way down the line in linear algebra and lost several points on the test because the instructor said I can't just claim -(a-b) = (b-a) so I had to prove 0-x = -x I guess.
In reverse polish, a b - 0 - = b a - 0 +. Because x is common, reorder the multiplication:
8 3 7 / - x * = 5
53 7 / x * = 5
Divide both sides by 53 / 7:
x = 5 53 7 / *
x = 5 53 * 7 /
x = 265 7 /
x = 37 6 7 / +
Solve for x.

Which of the following postfix notations correctly represents infix sum 1+2+3+4?

I am testing an infix-to-postfix-to-infix converter and found some kind of uncertainty. For example, a simple infix sum
1 + 2 + 3 + 4
can be converted to postfix one
1 2 + 3 + 4 +
assuming that operators with equal precedence are not accumulated. If they are then I get
1 2 3 4 + + +
On the other hand, all the following postfix expressions can be converted to the initial sum
1 2 + 3 + 4 +
1 2 + 3 4 + +
1 2 3 4 + + +
Are all these postfix expressions correct?
UPDATE1
If you would make such converter, to which form would you choose? I need to choose one for testing.
You need to define an extra constraint.
Mathematically, your postfix expressions are all the same. But on a computer integer addition is not really commutative because of overflow.
Replace 1 2 3 4 with a b c d and consider the possibility of overflow. Most programming languages define that a + b + c + d must be evaluated left-to-right so that a b + c + d + is the only correct translation.
Only when you define that the order of evaluation is 'unspecified' all the postfix versions are equivalent. That was the case for (older) C Compilers.
Yep, all correct. They correspond to the following bracketed infix expressions:
((1 + 2) + 3) + 4
(1 + 2) + (3 + 4)
1 + (2 + (3 + 4))
+ is confusing - it is commutative, so in fact, every result seems correct.
Consider replacing + with other operators: 1 a 2 b 3 c 4.
The correct result here, for left-associative operators, is
1 2 a 3 b 4 c
So, in your case, I'd expect 1 2 + 3 + 4 +

Resources