C#數據結構與演算法系列(十一):中綴表達式轉後綴表達式

1.具體步驟

1)初始化兩個棧:運算符棧s1和儲存中間結果的棧s2;
2)從左至右掃描中綴表達式;
3)遇到操作數時,將其壓s2;
4)遇到運算符時,比較其與s1棧頂運算符的優先順序:
     (1)如果s1為空,或棧頂運算符為左括弧「(」,則直接將此運算符入棧;
     (2)否則,若優先順序比棧頂運算符的高,也將運算符壓入s1;
     (3)否則,將s1棧頂的運算符彈出並壓入到s2中,再次轉到(4-1)與s1中新的棧頂運算符相比較;
5)遇到括弧時:
     (1)如果是左括弧「(」,則直接壓入s1
     (2)如果是右括弧「)」,則依次彈出s1棧頂的運算符,並壓入s2,直到遇到左括弧為止,此時將這一對括弧丟棄
6)重複步驟2至5,直到表達式的最右邊
7)將s1中剩餘的運算符依次彈出並壓入s2
8)依次彈出s2中的元素並輸出,結果的逆序即為中綴表達式對應的後綴表達式

2.思路分析

 

 

 3.程式碼實現

 /// <summary>
        /// 字元串轉中綴表達式的List
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static List<string> ToInfixExpression(string expression)
        {
            List<string> list = new List<string>();

            int index = 0;

            string str = "";

            do
            {

                //48-57ASCII碼代表的是0-9 如果不是0-9直接入鏈表
                if (expression[index] < 48 || expression[index] > 57)//ascii編碼
                {
                    list.Add("" + expression[index]);

                    index++;
                }
                else
                {
                    str = "";

                    //多位數判斷
                    while (index < expression.Length && expression[index] >= 48 && expression[index] <= 57)
                    {

                        str += expression[index];

                        index++;
                    }

                    list.Add(str);
                }

            } while (index < expression.Length);

            return list;
        }

 

    /// <summary>
        /// 中綴轉後綴
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static List<string> ParseSuffixExpression(List<string> expression)
        {
            //存儲中間結果
            List<string> list = new List<string>();
            //符號棧
            Stack<string> stack = new Stack<string>();

            foreach (var item in expression)
            {
                //多位數判斷 如果是數字直接加入list
                if (Regex.IsMatch(item, "\\d+"))
                {
                    list.Add(item);
                }
                //如果是左括弧,直接入符號棧
                else if (item.Equals("("))
                {
                    stack.Push(item);
                }
                //如果是右括弧
                else if (item.Equals(")"))
                {
                    //依次彈出stack棧頂的運算符,並存入list,直到遇到左括弧為止
                    while (!stack.Peek().Equals("("))
                    {                        
                        list.Add(stack.Pop());
                    }
                    //將(也出棧
                    stack.Pop();
                }
                //如果是*/+-
                else
                {
                    //循環判斷item的優先順序小於或者等於stack棧頂運算符,將stack棧頂的運算符出棧並加入到list中
                    while (stack.Count != 0 && Operation.GetValue(stack.Peek()) >= Operation.GetValue(item))
                    {
                        list.Add(stack.Pop());
                    }
                    //將item入棧
                    stack.Push(item);
                }
            }

            //將stack剩餘的運算符依次入list
            while (stack.Count!=0)
            {
                list.Add(stack.Pop());
            }

            return list;
        }

 

    public class Operation
    {
        private static int ADD = 1;
        private static int SUB = 1;
        private static int MUL = 2;
        private static int DIV = 2;

        public static int GetValue(string operation)
        {
            int result = 0;

            switch (operation)
            {
                case "+":
                    result = ADD;
                    break;
                case "-":
                    result = SUB;
                    break;
                case "*":
                    result = MUL;
                    break;
                case "/":
                    result = DIV;
                    break;
                default:
                   // Console.WriteLine("不存在該運算符");
                    break;
            }

            return result;
        }
    }

 

        /// <summary>
        /// 計算
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public static int Calculate(List<string> list)
        {
            //創建棧
            Stack<string> stack = new Stack<string>();

            //循環遍歷
            list.ForEach(item =>
            {
                //正則表達式判斷是否是數字,匹配的是多位數
                if (Regex.IsMatch(item,"\\d+"))
                {
                    //如果是數字直接入棧
                    stack.Push(item);
                }
                //如果是操作符
                else
                {
                    //出棧兩個數字,並運算,再入棧
                    int num1 =int.Parse(stack.Pop());

                    int num2 = int.Parse(stack.Pop());

                    int result = 0;

                    if(item.Equals("+"))
                    {
                        result = num2 + num1;
                    }
                    else if(item.Equals("*"))
                    {
                        result = num2 * num1;
                    }
                    else if(item.Equals("/"))
                    {
                        result = num2 / num1;
                    }
                    else if (item.Equals("-"))
                    {
                        result = num2 - num1;
                    }
                    else
                    {
                        throw new Exception("無法識別符號");
                    }

                    stack.Push(""+result);
                }
            });

            //最後把stack中數據返回
            return int.Parse(stack.Pop());
        }

 

    public class ReversePolandTransformation
    {

        public static void Test()
        {
            string expression = "1+((2+3)*4)-5";

            //將字元串轉換成List
            List<string> infixExpression = ToInfixExpression(expression);

            string str = "";

            infixExpression.ForEach(item =>
            {
                str = str + item + ",";
            });

            Console.WriteLine("中綴表達式對應的List:"+str);

            str = "";

            //將中綴表達式轉換成後綴表達式
            List<string> suffixExpression = ParseSuffixExpression(infixExpression);

            suffixExpression.ForEach(item =>
            {
                str = str + item + ",";
            });

            Console.WriteLine("\n後綴表達式對應的List:"+str);

            //結果計算
            int result =PolandNotation.Calculate(suffixExpression);

            Console.WriteLine($"\n{expression}={result}");
        }
   }