二叉树及其实例 三 ( Binary Tree c.)

表达式求值

1. 验证字符串为表达式

2.分拆表达式为操作符,操作数,括号

       确定操作符是二元或一元操作符

3.将操作符序列建立二叉树

4.对二叉树进行求值

    叶子节点为操作数,父节点为操作符,递归求值

 

Test :

[TestMethod()]
       public void CalculateTest()
       {
           BinTree<string> target = new BinTree<string>(); // TODO: Initialize to an appropriate value
           string src = "";

           double actual;
           double a;
         

           src = "-1.1+-2.2+3.3";
           a = -1.1+-2.2+3.3;
           actual = target.Calculate(src);
           Assert.IsTrue(Math.Abs(actual - a) < 0.001);

           src = "1+2 * 3 - -(-(3 + 2 - 4 * (2 + 5 + 3)))";
           a = 1 + 2 * 3 - -(-(3 + 2 - 4 * (2 + 5 + 3)));
           actual = target.Calculate(src);
          
           Assert.IsTrue(Math.Abs(actual - a) < 0.001);

           src = "-1.1--2.2";
           a = -1.1-(-2.2);
           actual = target.Calculate(src);
           Assert.IsTrue(Math.Abs(actual - a) < 0.001);

           src = "10.999+201*30--400*(5+60)+700.0/3+4%2 ";
               //"10.999+201*30--400*(5+60)+700/3+4%2";
           a = 10.999 + 201 * 30 - (-400 * (5 + 60)) + 700.0/3  + 4 % 2;
           actual = target.Calculate(src);
           Assert.IsTrue(Math.Abs(actual - a) < 0.001);

           src = "700.0/3+(-1.1)";           
           a = 700.0/ 3+(-1.1);
           actual = target.Calculate(src);
           Assert.IsTrue(Math.Abs(actual - a) < 0.001);

           src = "";
           a = 0;
           actual = target.Calculate(src);
           Assert.IsTrue(Math.Abs(actual - a) < 0.001);

           //not support number type ,treat all item as double
           //src = "10.999+201*30--400*(5+60)+7000/3+4%2 ";           
           //a = 10.999 + 201 * 30 - (-400 * (5 + 60)) + 7000 / 3 + 4 % 2;
           //actual = target.Calculate(src);
           //Assert.IsTrue(Math.Abs(actual - a) < 0.001);
       }

 

实现

public List<ExpressionItem> SpliteExpression(string src)
      {
          src = src.Replace(" ", "");
          List<ExpressionItem> ret = new List<ExpressionItem>();
          StringBuilder sb = new StringBuilder();

          StringReader sr = new StringReader(src);
          int val = sr.Read();

          ExpressionCellType currentType = ExpressionCellType.Unkown;
          ExpressionCellType nextType = ExpressionCellType.Unkown;
          ExpressionCellType prevType = ExpressionCellType.Unkown;

          while (val > 0)
          {
              char c = (char)val;

              sb.Append(c);
              currentType = GetExpressionItemType(sb.ToString());

              int nextVal = sr.Peek();
              char nextChar = (char)nextVal;
              string nextString = nextChar.ToString();
              nextType = GetExpressionItemType(nextString);

              if (IsOperand(sb.ToString() + nextString))
              {
                  nextType = ExpressionCellType.Operand;
              }

              if (nextType != currentType
                  ||
                  (
                   currentType == nextType
                   && currentType == ExpressionCellType.Operator
                  )
                )
              {
                  ExpressionItem item = new ExpressionItem();

                  item.Value = sb.ToString();
                  item.CellType = currentType;

                  if (currentType == ExpressionCellType.Operator)
                  {
                      item.CombineType = OperatorCombineType.Two;
                      if (prevType == ExpressionCellType.Unkown
                          || prevType == ExpressionCellType.Operator)
                      {
                          if (item.Value == "("
                              || item.Value == ")"
                              )
                          {
                              item.CombineType = OperatorCombineType.Bracket;
                          }
                          else if (item.Value == "-")
                          {
                              item.CombineType = OperatorCombineType.One;
                          }
                      }

                  }

                  prevType = currentType;
                  ret.Add(item);
                  sb.Clear();
              }

              val = sr.Read();
          }

          return ret;
      }

public Int32 GetPriority(ExpressionItem item)
      {
          Int32 priority = -1;

          if (item.CombineType == OperatorCombineType.One)
          {
              priority += 100;
          }
          else if (item.CombineType == OperatorCombineType.Two)
          {
              if ("+-".IndexOf(item.Value) > -1)
              {
                  priority += 5;
              }
              else if ("*/%".IndexOf(item.Value) > -1)
              {
                  priority += 10;
              }
          }

          return priority;
      }

 

private ExpressionCellType GetExpressionItemType(string p)
       {
           if (IsOperand(p))
           {
               return ExpressionCellType.Operand;
           }
           else if (IsOperator(p))
           {
               return ExpressionCellType.Operator;
           }
           else
           {
               return ExpressionCellType.Unkown;
           }
       }

public bool IsOperand(string src)
      {
          double d;
          bool result = double.TryParse(src, out d);

          return result;

      }

      public bool IsOperator(string src)
      {
          if (src == null)
          {
              return false;
          }

          if (src.Equals("+", StringComparison.OrdinalIgnoreCase)
              || src.Equals("-", StringComparison.OrdinalIgnoreCase)
              || src.Equals("*", StringComparison.OrdinalIgnoreCase)
              || src.Equals("/", StringComparison.OrdinalIgnoreCase)
              || src.Equals("%", StringComparison.OrdinalIgnoreCase)
              || src.Equals("(", StringComparison.OrdinalIgnoreCase)
              || src.Equals(")", StringComparison.OrdinalIgnoreCase)
              // || src.Equals("-(", StringComparison.OrdinalIgnoreCase)
              )
          {
              return true;
          }

          else
          {
              return false;
          }

      }

 

/// <summary>
      /// support unary operator
      /// </summary>
      /// <param name="expressionString"></param>
      /// <returns></returns>
      public BinTree<ExpressionItem> Expression2Bintree2(string expressionString)
      {
          List<ExpressionItem> items = SpliteExpression(expressionString);

          if (items == null || items.Count == 0)
          {
              return null;
          }

          BinTree<ExpressionItem> result = new BinTree<ExpressionItem>();
          BinTreeNode<ExpressionItem> parent = null;

          Stack<BinTreeNode<ExpressionItem>> operators = new Stack<BinTreeNode<ExpressionItem>>();
          Stack<BinTreeNode<ExpressionItem>> operands = new Stack<BinTreeNode<ExpressionItem>>();
          int i = 0;
          while (i < items.Count)
          {
              ExpressionItem item = items[i];
              BinTreeNode<ExpressionItem> itemNode = new BinTreeNode<ExpressionItem>();
              itemNode.Value = item;

              if (item.CellType == ExpressionCellType.Operand)
              {
                  operands.Push(itemNode);
              }
              else if (item.CellType == ExpressionCellType.Operator)
              {
                  if (item.Value == "("
                      )
                  {
                      operators.Push(itemNode);
                  }
                  else if (item.Value == ")")
                  {
                      //collapse untill (
                      //todo
                      bool notReachPrevBracket = true;
                      do
                      {
                          parent = operators.Pop();
                          if (parent.Value.CombineType == OperatorCombineType.Two)
                          {
                              BinTreeNode<ExpressionItem> oprand2 = operands.Pop();
                              BinTreeNode<ExpressionItem> oprand1 = operands.Pop();
                              parent.LeftChild = oprand1;
                              parent.RightChild = oprand2;
                          }
                          else if (parent.Value.CombineType == OperatorCombineType.One)
                          {
                              BinTreeNode<ExpressionItem> oprand1 = operands.Pop();
                              parent.LeftChild = oprand1;
                          }

                          operands.Push(parent);

                          if (operators.Count > 0)
                          {
                              BinTreeNode<ExpressionItem> prevNode = operators.Peek();//"("
                              if (prevNode.Value.Value == "("
                                  )
                              {
                                  notReachPrevBracket = false;
                                  operators.Pop();
                              }
                          }

                      } while (notReachPrevBracket && operators.Count > 0);
                  }
                  else
                  {
                      //while

                      while (operators.Count > 0
                            &&
                            (
                              GetPriority(item) <=
                              GetPriority(operators.Peek().Value)
                              )
                          )
                      {
                          parent = operators.Pop();
                          if (parent.Value.CombineType == OperatorCombineType.Two)
                          {
                              BinTreeNode<ExpressionItem> oprand2 = operands.Pop();
                              BinTreeNode<ExpressionItem> oprand1 = operands.Pop();
                              parent.LeftChild = oprand1;
                              parent.RightChild = oprand2;

                          }
                          else if (parent.Value.CombineType == OperatorCombineType.One)
                          {
                              BinTreeNode<ExpressionItem> oprand1 = operands.Pop();
                              parent.LeftChild = oprand1;
                          }

                          operands.Push(parent);
                      }

                      operators.Push(itemNode);
                  }
              }

              i++;
          }

          while (operators.Count > 0)
          {
              parent = operators.Pop();
              if (parent.Value.CombineType == OperatorCombineType.Two)
              {
                  BinTreeNode<ExpressionItem> oprand2 = operands.Pop();
                  BinTreeNode<ExpressionItem> oprand1 = operands.Pop();
                  parent.LeftChild = oprand1;
                  parent.RightChild = oprand2;
              }
              else if (parent.Value.CombineType == OperatorCombineType.One)
              {
                  BinTreeNode<ExpressionItem> oprand1 = operands.Pop();
                  parent.LeftChild = oprand1;
              }

              operands.Push(parent);
          }

          result.Root = operands.Pop();

          return result;

      }

 

public double BintreeNodeCollapseRecursive(BinTreeNode<string> parent)
       {
           double result = double.MinValue;

           if (parent.LeftChild == null
                && parent.RightChild == null
               )
           {
               return double.Parse(parent.Value);
           }
           else
           {
               double left = BintreeNodeCollapseRecursive(parent.LeftChild);
               double right = BintreeNodeCollapseRecursive(parent.RightChild);
               result = Calculate(left, parent.Value, right);
           }

           return result;
       }

       public double BintreeNodeCollapseRecursive2(BinTreeNode<ExpressionItem> parent)
       {
           double result = double.MinValue;

           if (parent == null)
           {
               return double.MinValue;
           }

           if (parent.LeftChild == null
                && parent.RightChild == null
               )
           {
               return double.Parse(parent.Value.Value);
           }
           else
           {
               double left = BintreeNodeCollapseRecursive2(parent.LeftChild);
               double right = BintreeNodeCollapseRecursive2(parent.RightChild);

               if (parent.Value.CombineType == OperatorCombineType.Two)
               {
                   result = Calculate(left, parent.Value.Value, right);
               }
               else if (parent.Value.CombineType == OperatorCombineType.One)
               {
                   result = Calculate(left, parent.Value.Value);
               }
           }

           return result;
       }

 

private double Calculate(double left, string operatorString)
       {
           double result = 0;
           switch (operatorString)
           {

               case "-":
                   result = -1 * left;
                   break;
               default:
                   break;
           }

           return result;
       }

       private double Calculate(double left, string operatorString, double right)
       {
           double result = 0;
           switch (operatorString)
           {
               case "+":
                   result = left + right;
                   break;
               case "-":
                   result = left - right;
                   break;
               case "*":
                   result = left * right;
                   break;
               case "/":
                   result = left / right;
                   break;
               case "%":
                   result = left % right;
                   break;
               default:
                   break;
           }

           return result;

 

       }

转载于:https://www.cnblogs.com/netfuns/archive/2011/07/29/2120953.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值