Exemple #1
0
 //叶子结点的构造方法
 public Node(string value)
 {
     this.Left = null;
     this.Right = null;
     this.Value = value;
 }
Exemple #2
0
 //修正树结构,并计算得出最后的值。
 //修正包括范围:
 //1.减法中产生负数的情况(包括 有括号 与 无括号式子)
 //2.除法中需要整除的情况(这里只会修复有括号式子,无括号式子的情况已经在生成时修复了)
 //3.除法出现除数为0的情况(全部修复)
 public Fraction AmendTreeAndCalculate(Node root,int leftRange)
 {
     if (root.Left == null && root.Right == null)
         return (Fraction)root.Value;
     switch(root.Value)
     {
         case "+":return AmendTreeAndCalculate(root.Left,leftRange)+ AmendTreeAndCalculate(root.Right,leftRange);
         case "-":
             Fraction LExp = AmendTreeAndCalculate(root.Left,leftRange);
             Fraction RExp = AmendTreeAndCalculate(root.Right,leftRange);
             //如果结果为负数的话且是没有括号的式子
             //不允许结果中出现负数的话,就把两颗子树翻转
             //并且要重新生成中缀表达式和最小表达式
             if ((RExp > LExp) & !HasNegative & HasBrack)
                 Transfer(root);
             //针对没有括号的情况
             else if((RExp > LExp) & !HasNegative)
             {
                 root.Value = "+";
                 return LExp + RExp;
             }
             return LExp - RExp;
         case "×":return AmendTreeAndCalculate(root.Left,leftRange) * AmendTreeAndCalculate(root.Right,leftRange);
         case "÷":
             Fraction divider = AmendTreeAndCalculate(root.Left,leftRange) ;
             Fraction divisor = AmendTreeAndCalculate(root.Right,leftRange);
             //如果发现被除数不是0,而除数是0的话,就翻转两颗子树
             if (divisor.GetMo() == 0 && divider.GetMo() != 0)
             {
                 Transfer(root);
                 return 0;
             }
             //如果不幸发现被除数和除数同时为0的话,那么还是默默地改掉这个符号吧...
             else if (divisor.GetMo() == 0 && divider.GetMo() == 0)
             {
                 //除法自此改名为加法
                 root.Value = "+";
                 return 0;
             }
             //如果在满足了有效性的条件下,突然发现老板加了任务:你必须给我搞个整除出来,咋办?
             if(!HasFrac)
             {
                 //如果你天生就能整除,我何必遭受这个罪呢...
                 if (divider.GetMo() % divisor.GetMo() == 0)
                     return divider.GetMo() / divisor.GetMo();
                 //但如果你天生不能整除可咋办呢?
                 else
                 {
                     //求得左侧被除数随机化产生的一个因子
                     int iRnd = DateTime.Now.Millisecond;
                     Random rand = new Random(iRnd);
                     //注意这里值域的下限
                     int a = rand.Next(leftRange, Math.Abs((int)divider.GetMo()));
                     long gcd = Fraction.GetGCD(divider.GetMo(), a);
                     //舍弃右侧原有子树,使用新的结点来代替,除法结果是 divider / gcd
                     root.Right =new Node(new Fraction(gcd, 1).ToString());
                     return divider.GetMo() / gcd;
                 }
             }
             return divider / divisor;
         default:
             throw new MyException.OwnDivException("啊呀呀,在计算的时候出了奇怪的错误。");
     }
 }
Exemple #3
0
 //翻转子树,为了修补程序所用
 public void Transfer(Node root)
 {
     Node Temp;
     Temp = root.Left;
     root.Left = root.Right;
     root.Right = Temp;
 }
Exemple #4
0
 //非叶结点的构造方法(非叶结点必然含有两个子结点)
 public Node(string value, Node left,Node right)
 {
     this.Left = left;
     this.Right = right;
     this.Value = value;
 }
Exemple #5
0
 //将一个后缀表达式转换为一个二叉树
 public void SuffixToTree(string Suffix)
 {
     Stack<Node> Stack = new Stack<Node>();
     string[] split = Suffix.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
     foreach(string token in split)
     {
         if (token == "-" || token == "+" || token == "×" || token == "÷")
         {
             //栈中先弹出的是右儿子
             Node RChild = Stack.Pop();
             //后弹出的是左儿子
             Node LChild = Stack.Pop();
             //以左结点与右结点和当前键值构建根结点,并压入栈
             Node tokenRoot = new Node(token, LChild, RChild);
             Stack.Push(tokenRoot);
         }
         //否则可能是等号,则令当前Root=栈顶的结点
         else if (token == "=")
         {
             Root = Stack.Pop();
             break;
         }
         //如果是操作数的话需要压栈
         else
             Stack.Push(new Node(token));
     }
 }
Exemple #6
0
 //在修补不带括号的表达式后要重新生成一下其表达式,同样不能带括号
 public string InOrderToInfixWithoutBrack(Node root)
 {
     if (root.Left == null && root.Right == null)
         return root.Value;
     return InOrderToInfixWithoutBrack(root.Left) + " " + root.Value +
     " " + InOrderToInfixWithoutBrack(root.Right);
 }
Exemple #7
0
 //通过层次遍历的方法直接生成一颗二叉树
 //  public void GenerateBinaryTree(Fraction[] numbers,string[] operation)
 //  {
 //      //将两个数组混合成为一个队列,当队列为空时标明二叉树建立成功
 //      Queue<Node> Nodes = new Queue<Node>();
 //      foreach(string op in operation)
 //          Nodes.Enqueue(new Node(op));
 //      foreach(Fraction num in numbers)
 //          Nodes.Enqueue(new Node(num.ToString()));
 //      //设立一个队列用于按层次构建二叉树
 //      Queue<Node> NodeQ = new Queue<Node>();
 //      //以Nodes[0]建立根结点
 //      //从待选取队列中除去头结点
 //      Root = Nodes.Dequeue();
 //      //根结点入队
 //      NodeQ.Enqueue(Root);
 //      //当待选取队列不为空的时候要一直出队入队进行
 //      while (Nodes.Count()!=0)
 //      {
 //          //头结点出队
 //          Node Head = NodeQ.Dequeue();
 //          //如果没有左结点,则从Nodes中获取
 //          if (Head.Left == null)
 //              Head.Left = Nodes.Dequeue();
 //          //由于该结点已经被选取了并加入了树中,所以加入NodeQ中
 //          NodeQ.Enqueue(Head.Left);
 //          //如果没有右结点,则从Nodes中获取
 //          if (Head.Right == null)
 //              Head.Right = Nodes.Dequeue();
 //          //由于右结点已经被选取了并加入了树中,所以加入NodeQ中
 //          NodeQ.Enqueue(Head.Right);
 //      }
 //  }
 //中序遍历得到二叉树对应中缀表达式
 public string InOrderToInfixWithBrack(Node root)
 {
     //如果不是为叶结点或者不是根结点,则加括号
     if (!root.IsLeaf() && root != Root)
         return "( " + InOrderToInfixWithBrack(root.Left) + " " + root.Value +
             " " + InOrderToInfixWithBrack(root.Right) + " )";
     //如果不是叶结点却是根结点
     else if (!root.IsLeaf())
         return InOrderToInfixWithBrack(root.Left) + " " + root.Value +
             " " + InOrderToInfixWithBrack(root.Right);
     else
         return root.Value;
 }
Exemple #8
0
 //根据root递归生成最小表示法获得的字符串
 public string GenerateMinusExp(Node root)
 {
     //如果是叶结点的话,则直接返回该结点的值
     if (root.IsLeaf())
         return root.Value;
     else if (root.Value == "+" || root.Value == "×")
     {
         //对左子树进行递归,得到左子树的最小表示字符串
         string LeftMinus = GenerateMinusExp(root.Left);
         //对右子树进行递归,得到右子树的最小表示字符串
         string RightMinus = GenerateMinusExp(root.Right);
         //对左子树和右子树进行统一排序
         if (string.Compare(LeftMinus, RightMinus) <= 0)
             return root.Value + LeftMinus + RightMinus;
         else
             return root.Value + RightMinus + LeftMinus;
     }
     //否则就按照正常次序进行最小字符串表示
     else
         return root.Value + GenerateMinusExp(root.Left) + GenerateMinusExp(root.Right);
 }
Exemple #9
0
 public void GenerateBinaryTree(ref Node root,ref Stack<Fraction> StackNum,ref Stack<string> StackOp,Random rand)
 {
     //先看是不是根结点
     if(root==null)
         root = new Node(StackOp.Pop());
     if(StackOp.Count()==0)
     {
         root.Left = new Node(StackNum.Pop().ToString());
         root.Right = new Node(StackNum.Pop().ToString());
         return;
     }
     int RandKey = rand.Next(0,3);
     //如果两边都是符号的话,则两边都递归
     if(RandKey==0)
     {
         root.Left = new Node(StackOp.Pop());
         //一次Pop之后栈可能为空了,所以要注意判断
         if (StackOp.Count == 0)
         {
             //如果栈空了要注意对左侧进行递归
             root.Right = new Node(StackNum.Pop().ToString());
             GenerateBinaryTree(ref root.Left, ref StackNum, ref StackOp, rand);
         }
         else
         {
             root.Right = new Node(StackOp.Pop());
             GenerateBinaryTree(ref root.Left, ref StackNum, ref StackOp, rand);
             GenerateBinaryTree(ref root.Right, ref StackNum, ref StackOp, rand);
         }
     }
     //如果左边是符号,右边是数字的话,则只进行左边的递归
     else if(RandKey==1)
     {
         root.Left = new Node(StackOp.Pop());
         root.Right = new Node(StackNum.Pop().ToString());
         GenerateBinaryTree(ref root.Left,ref StackNum,ref StackOp,rand);
     }
     //如果右边是符号,左边是数字的话,则只进行右边的递归
     else{
         root.Right = new Node(StackOp.Pop());
         root.Left = new Node(StackNum.Pop().ToString());
         GenerateBinaryTree(ref root.Right,ref StackNum,ref StackOp,rand);
     }
 }