Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Postfix notation to expression tree

There are enough resources on how to convert an expression tree into postfix notation, and it's not that hard.

But I have to parse a postfix expression into an expression tree.

The expression is:

A 2 ^ 2 A * B * - B 2 ^ + A B - /

I don't really have a clue on how to interpret the expression. Does someone has a clue on how to proces this?

like image 607
Ikke Avatar asked Jan 08 '09 11:01

Ikke


People also ask

How an postfix expression notation is converted to an expression tree?

The construction of the expression tree takes place by reading the postfix expression one symbol at a time. If the symbol is an operand, a new binary tree node is created, and its pointer is pushed onto a stack.

What is the postfix expression for the given expression tree?

What is the postfix expression for the following expression tree? Explanation: If the given expression tree is evaluated, the postfix expression ab+cde+** is obtained.


2 Answers

Create a stack containing nodes that could be part of a tree

  1. Push operands on a stack (A, 2, B, etc. are operands) as leaf-nodes, not bound to any tree in any direction
  2. For operators, pop the necessary operands off the stack, create a node with the operator at the top, and the operands hanging below it, push the new node onto the stack

For your data:

  1. Push A onto the stack
  2. Push 2 onto the stack
  3. Pop 2 and A, create ^-node (with A and 2 below), push it on the stack
  4. Push 2 on stack
  5. Push A on stack
  6. Pop A and 2 and combine to form the *-node
  7. etc.
  8. etc.

tree structure

Here is a LINQPad program that can be experimented with:

// Add the following two using-directives to LINQPad:
// System.Drawing
// System.Drawing.Imaging

static Bitmap _Dummy = new Bitmap(16, 16, PixelFormat.Format24bppRgb);
static Font _Font = new Font("Arial", 12);

void Main()
{
    var elementsAsString = "A 2 ^ 2 A * B * - B 2 ^ + A B - / 2 ^";
    var elements = elementsAsString.Split(' ');

    var stack = new Stack<Node>();
    foreach (var element in elements)
        if (IsOperator(element))
        {
            Node rightOperand = stack.Pop();
            Node leftOperand = stack.Pop();
            stack.Push(new Node(element, leftOperand, rightOperand));
        }
        else
            stack.Push(new Node(element));

    Visualize(stack.Pop());
}

void Visualize(Node node)
{
    node.ToBitmap().Dump();
}

class Node
{
    public Node(string value)
        : this(value, null, null)
    {
    }

    public Node(string value, Node left, Node right)
    {
        Value = value;
        Left = left;
        Right = right;
    }

    public string Value;
    public Node Left;
    public Node Right;

    public Bitmap ToBitmap()
    {
        Size valueSize;
        using (Graphics g = Graphics.FromImage(_Dummy))
        {
            var tempSize = g.MeasureString(Value, _Font);
            valueSize = new Size((int)tempSize.Width + 4, (int)tempSize.Height + 4);
        }

        Bitmap bitmap;
        Color valueColor = Color.LightPink;
        if (Left == null && Right == null)
        {
            bitmap = new Bitmap(valueSize.Width, valueSize.Height);
            valueColor = Color.LightGreen;
        }
        else
        {
            using (var leftBitmap = Left.ToBitmap())
            using (var rightBitmap = Right.ToBitmap())
            {
                int subNodeHeight = Math.Max(leftBitmap.Height, rightBitmap.Height);
                bitmap = new Bitmap(
                    leftBitmap.Width + rightBitmap.Width + valueSize.Width,
                    valueSize.Height + 32 + subNodeHeight);

                using (var g = Graphics.FromImage(bitmap))
                {
                    int baseY  = valueSize.Height + 32;

                    int leftTop = baseY; // + (subNodeHeight - leftBitmap.Height) / 2;
                    g.DrawImage(leftBitmap, 0, leftTop);

                    int rightTop = baseY; // + (subNodeHeight - rightBitmap.Height) / 2;
                    g.DrawImage(rightBitmap, bitmap.Width - rightBitmap.Width, rightTop);

                    g.DrawLine(Pens.Black, bitmap.Width / 2 - 4, valueSize.Height, leftBitmap.Width / 2, leftTop);
                    g.DrawLine(Pens.Black, bitmap.Width / 2 + 4, valueSize.Height, bitmap.Width - rightBitmap.Width / 2, rightTop);
                }
            }
        }

        using (var g = Graphics.FromImage(bitmap))
        {
            float x = (bitmap.Width - valueSize.Width) / 2;
            using (var b = new SolidBrush(valueColor))
                g.FillRectangle(b, x, 0, valueSize.Width - 1, valueSize.Height - 1);
            g.DrawRectangle(Pens.Black, x, 0, valueSize.Width - 1, valueSize.Height - 1);
            g.DrawString(Value, _Font, Brushes.Black, x + 1, 2);
        }

        return bitmap;
    }
}

bool IsOperator(string s)
{
    switch (s)
    {
        case "*":
        case "/":
        case "^":
        case "+":
        case "-":
            return true;

        default:
            return false;
    }
}

Output:

LINQPad output

like image 172
Lasse V. Karlsen Avatar answered Oct 26 '22 07:10

Lasse V. Karlsen


Does this look correct:

for n in items:
    if n is argument:
        push n
    if n is operator:
        b = pop      // first pop shall yield second operand   
        a = pop      // second pop shall yield first operand
        push a+n+b
 answer = pop



A 2 ^ 2 A * B * - B 2 ^ + A B - /

Running this on your statment should yield a stack that evolves like this:

[A]
[A, 2]
[A^2]
[A^2, 2]
[A^2, 2, A]
[A^2, 2*A]
[A^2, 2*A, B]
[A^2, 2*A*B]
[A^2-2*A*B]
[A^2-2*A*B, B]
[A^2-2*A*B, B, 2]
[A^2-2*A*B, B^2]
[A^2-2*A*B+B^2]
[A^2-2*A*B+B^2, A]
[A^2-2*A*B+B^2, A, B]
[A^2-2*A*B+B^2, A-B]
[A^2-2*A*B+B^2/A-B]
like image 38
Staale Avatar answered Oct 26 '22 07:10

Staale