Example #1
0
        //Note:生成一颗不可能带括号的树
        //步骤:先生成一个中缀表达式,再生成一颗二叉树
        public void GenerateTreeWithoutBrack(Fraction[] numbers, string[] operations, Random rand, int leftRange)
        {
            StringBuilder temp = new StringBuilder();

            //通过给定的numbers和operations生成不带括号的中缀表达式
            for (int i = 0; i < numbers.Count(); i++)
            {
                temp.Append(numbers[i].ToString() + " ");
                //在生成不带括号的表达式时,必须得学会反转
                if (i == numbers.Count() - 1)
                {
                    break;
                }
                //如果不带括号表达中出现了 x/0的情况,由于除法是左结合所以只要保证除法右侧的数不为0即可
                if (operations[i] == "÷" && numbers[i + 1].GetMo() == 0)
                {
                    numbers[i + 1] = new Fraction(1, 1);
                }
                //要求整除的前提下,这时候都是整数参与运算,没有分数
                else if (operations[i] == "÷" && !HasFrac)
                {
                    //如果本来就整除就不需要费事了...
                    if (numbers[i].GetMo() % numbers[i + 1].GetMo() != 0 &&
                        (i == 0 || operations[i - 1] == "+" || operations[i - 1] == "-" || operations[i - 1] == "×"))
                    {
                        //在leftRange到numbers[i]的范围内取一随机数,求它与numbers[i]的分子的最大公约数
                        int  a   = rand.Next(leftRange, Math.Abs((int)numbers[i].GetMo()) + 1);
                        long gcd = Fraction.GetGCD(numbers[i].GetMo(), a);
                        //令numbers[i+1]的值为该数
                        numbers[i + 1] = new Fraction(gcd, 1);
                    }
                }
                temp.Append(operations[i] + " ");
            }
            //获得了不带括号的中缀表达式,接下来要将它变为一颗树,这里一定要带=,这是判断的条件之一
            TreeInfix = temp.ToString() + " =";
            //中缀表达式要先转成后缀表达式
            string Suffix = InfixToSuffix(TreeInfix);

            //后缀表达式转成树,设置Root为根结点
            SuffixToTree(Suffix);
            //通过对树的修补进行表达式的合法化
            Answer = AmendTreeAndCalculate(this.Root, leftRange).ToString();
            //重新生成一个中缀表达式(不加任何括号的)
            TreeInfix = InOrderToInfixWithoutBrack(this.Root) + " =";
            //通过最小表示法生成最小表示序列
            TreeMinusLamda = GenerateMinusExp(this.Root);
        }
Example #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("啊呀呀,在计算的时候出了奇怪的错误。");
            }
        }