using System;
using System.Collections.Generic;


class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 返回表达式的值
     * @param s string字符串 待计算的表达式
     * @return int整型
     */
     Stack<Char> ops = new Stack<char>();
        Stack<int> nums = new Stack<int>();
        Dictionary<char, int> D = new Dictionary<char, int>();
        

        public Solution()
        {
            D.Add('(', 1);
            D.Add('+', 3);
            D.Add('-', 3);
            D.Add(')', 4);
            D.Add('s', 5);
            D.Add('@', 0);  //乘以10的运算
            D.Add('*', 2);
        }

        public int solve(string s)
        {
            // write code here
            ops.Clear();
            nums.Clear();
            for (int i = 0; i < s.Length; i++)
            {
                if (i == s.Length - 1)
                    handle(s[i], 's');
                else
                    handle(s[i], s[i + 1]);
            }
            while(nums.Count>1)
            {
                Shrink();
            }
            return nums.Pop();
        }
        public void handle(char c, char next)
        {
            if (c >= '0' && c <= '9')
            {
                //是连续两个数字
                if (next >= '0' && next <= '9')
                {
                    int newC = -1000;
                    if (ops.Count > 0 && ops.Peek() == '@')
                    {
                        newC = Cal(nums.Pop(), c - '0', ops.Pop());
                        nums.Push(newC);
                        ops.Push('@');
                    }
                    else
                    {
                        nums.Push(c - '0');
                        ops.Push('@');
                    }
                    return;

                }


                //不是连续两个数字
                if (nums.Count > 0 && ops.Count > 0)
                {
                   if (D[next] >= D[ops.Peek()] && ops.Peek()!='(')
                    {
                        int start = nums.Pop();
                        int end = c - '0';
                        char op = ops.Pop();
                        int num = Cal(start, end, op);
                        nums.Push(num);
                        while(ops.Count>0&& D[next]>=D[ops.Peek()] && nums.Count>=2 && ops.Peek()!='(')
                        {
                            Shrink();
                        }
                        return;
                    }
                    
                }
                nums.Push(c - '0');
                    // ops.Push()
                return;
            }
            if (c == '+' || c == '-' || c == '*' || c == '(')
            {
                ops.Push(c);
            }
            if (c == ')')
            {
                //int start, end, num;
                //char op;
                while (ops.Peek() != '(')
                {
                    //end = nums.Pop();
                    //op = ops.Pop();
                    //start = nums.Pop();
                    //num = Cal(start, end, op);
                    //nums.Push(num);
                    Shrink();
                }
                ops.Pop();
            }
        }

        private void Shrink()
        {
            int start, end, num;
            char op;
            end = nums.Pop();
            op = ops.Pop();
            start = nums.Pop();
            num = Cal(start, end, op);
            nums.Push(num);
        }

        private int Cal(int s, int e, char op)
        {
            switch (op)
            {
                case '+':
                    return s + e;
                case '-':
                    return s - e;
                case '*':
                    return s * e;
                case '@':
                    return s * 10 + e;
                default:
                    return int.MinValue;

            }
        }
}
写的有点混乱,但是思路应该很容易理解:
1. 要定义非字母符号的优先级
2. 考虑到数字不是个位,因为这里添加了‘@’符号,如果一个数a后面仍然是数b,那么插入下一个数时,会取出上一个数进位,将1*10+b放入;但是如果首位时两个数字,那么第一个无法进位,这里表现为一个判断
3.每次输入数字时,会进行判断,如果数字后面的字符优先级不高于栈定符号的优先级,那么就进行运算:1+2+3,到2的时候,发现第二个加号优先级不高于1,故先将见面的计算出来,将数字入栈
4.如果后面的优先级高于栈顶的优先级 ,那么只能先将数字存入,后面在算 :例如 1+2*3 ,到2的时候只能先存入
5.考虑到括号存在,“("优先级高于任何算数,只能因”)“出现而成对销毁 
6. shrink函数是收缩的意思,九世纪因为后面某个运算成功,导致前面一堆可以计算时,就先计算,例如 (1-(2-(10+3*4)))*5-6, 当最内的3*4计算完得到12入nums栈,但此时可以继续计算 10+12操作,这里就会调用Shrink函数,但是”(“运算符优先级高,不能拿出来运算
7.因为每次要传入当前字符和下一个字符,因此在最后一个字符遍历时,它的下一个字符手动设为”s',