Postfix表示法到表达式树

时间:2009-01-08 11:05:47

标签: algorithm language-agnostic

有足够的资源可以将表达式树转换为后缀表示法,并不是那么难。

但我必须将后缀表达式解析为表达式树。

表达式是:

  

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

我真的不知道如何解释表达式。有人知道如何处理这个问题吗?

2 个答案:

答案 0 :(得分:55)

创建一个包含可能属于树的节点的堆栈

  1. 将堆栈上的操作数(A,2,B等操作数)推送为叶子节点,而不是绑定到任何方向的任何树
  2. 对于操作员,从堆栈中弹出必要的操作数,在顶部创建一个操作符,并在其下面挂起操作数,将新节点压入堆栈
  3. 对于您的数据:

    1. 将A推入堆栈
    2. 将2推入堆栈
    3. 弹出2和A,创建^ -node(下面有A和2),将其推入堆栈
    4. 在堆栈上按2
    5. 在堆栈上推送A
    6. 弹出A和2并组合形成* -node
    7. tree structure

      这是一个可以试用的LINQPad程序:

      // 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;
          }
      }
      

      输出:

      LINQPad output

答案 1 :(得分:5)

这看起来是否正确:

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 - /

在你的声明上运行它应该会产生一个像这样发展的堆栈:

[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]