c#实现逆波兰转换与计算

/*
1)遇到操作数,直接输出
2)遇到左括号,进栈
3)遇到右括号,逐个将括号内元素出栈并输出,最后弹出左括号
4)遇到运算符,从栈中弹出元素并输出直到遇到发现更低优先级的元素(或者栈为空)为止,再将遇到的运算符入栈
5)最后栈中所有元素依次弹出并输出
*/

/// <summary>  
/// 逆波兰计算器  
/// </summary>  
static class RPNCalculator  
{  
   /// <summary>  
   /// 逆波兰计算器  
   /// </summary>  
   /// <param name="ls">中缀表达式</param>  
   /// <returns>运算结果</returns>  
    public static double Start(List<string> ls)=>GetValue(Transform(ls));  
    /// <summary>  
    /// 获取运算符优先级  
    /// </summary>  
    /// <param name="str">运算符串</param>  
    /// <returns>优先级</returns>  
    private static int GetPriorLevel(string str)  
    {  
        switch (str\[0\])  
        {  
            case '+':  
            case '-':  
                return 1;  
            case '*':  
            case '/':  
                return 2;  
            case '^':  
                return 3;  
            default:  
                return 0;  
        }  
    }  
    /// <summary>  
    /// 二元运算  
    /// </summary>  
    /// <param name="op">运算符</param>  
    /// <param name="x">第一个数</param>  
    /// <param name="y">第二个树</param>  
    /// <returns>运算结果</returns>  
    private static double Calculate(string op,double x, double y)  
    {  
        switch (op)  
        {  
            case "+":  
                return y+x;  
            case "-":  
                return y-x;  
            case "*":  
                return y*x;  
            case "/":  
                return y/x;  
            case "^":  
                return Math.Pow(y, x);  
            default:  
                return 0;  
        }  
    }  
    /// <summary>  
    /// 是否是数字  
    /// </summary>  
    /// <param name="str">字符串</param>  
    /// <returns>布尔值</returns>  
    private static bool IsNum(string str) => Regex.IsMatch(str, @"^(-?\\d+)(\\.\\d+)?$");  
    /// <summary>  
    /// 逆波兰转换  
    /// </summary>  
    /// <param name="str">中缀表达式</param>  
    /// <returns>逆波兰式</returns>  
    private static List<string> Transform(List<string> ls)  
    {  
#if TEST  
        foreach (var item in ls)  
            Write(item + " ");  
        WriteLine();  
#endif  
        //存放转换结果  
        List<string> ans = new List<string>();  
        //栈  
        SQStack<string> sk = new SQStack<string>();  
        for(int i=0;i<ls.Count;++i)  
        {  
            var item = ls\[i\].Trim();  
            //如果是数字,直接输出  
            if (IsNum(item))  
                ans.Add(item);  
            //如果是"(",进栈  
            else if (item == "(")  
                sk.Push(item);  
            //如果是")",括号内的元素出栈并输出  
            else if (item == ")")  
            {  
                while (sk.GetTop() != "(")  
                    ans.Add(sk.Pop());  
                sk.Pop();//并将"("出栈  
            }  
            //其他运算符的情况  
            else  
            {  
                //栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止  
                while (!sk.IsEmpty() && GetPriorLevel(sk.GetTop()) > GetPriorLevel(item))  
                    ls.Add(sk.Pop());  
                sk.Push(item);//运算符入栈  
            }  
        }  
        //输入末尾,所有元素依次弹出  
        while (!sk.IsEmpty())  
            ans.Add(sk.Pop());  
        return ans;  
    }  
    /// <summary>  
    /// 逆波兰求值  
    /// </summary>  
    /// <param name="ls">逆波兰式</param>  
    /// <returns>运算结果</returns>  
    private static double GetValue(List<string> ls)  
    {  
#if TEST  
        foreach (var item in ls)  
            Write(item + " ");  
        WriteLine();  
#endif  
        SQStack<double> sk = new SQStack<double>();  
        foreach (var item in ls)  
        {  
            //遇到数字就进栈  
            if(IsNum(item))  
                sk.Push(double.Parse(item));  
            else//否则遇到符号,出栈两个数字并运算  
              sk.Push(Calculate(item, sk.Pop(), sk.Pop()));//运算结果进栈  
        }  
        return sk.Pop();  
    }  
}

转载于:https://my.oschina.net/u/3848121/blog/1919776

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值