資料結構學習筆記三:算符優先演算法

來源:互聯網
上載者:User

給出一個運算式 2*(3-1),迅雷不及掩耳,立馬知道答案為4,但是電腦可沒有這樣的能耐,它只知道直接計算,卻不知道優先順序。如此,我們需要自己用代碼來告訴它算符的優先順序

  1. 從左至右
  2. 先乘除後加減
  3. 先括弧內後括弧外

先來研究簡單的算術運算式,只有+-*/()運算子

算符優先表如,其中#為結束標識符。

現在來糾結具體的實現。

/// <summary>/// 返回兩運算子的優先順序/// </summary>/// <param name="first"></param>/// <param name="last"></param>/// <returns>">, < , ="</returns>private char Precede(char first, char last){    string operate = "+-*/()#";    char[,] level = new char[7, 7]{                                                 {'>','>','<','<','<','>','>'},                                                 {'>','>','<','<','<','>','>'},                                                 {'>','>','>','>','<','>','>'},                                                 {'>','>','<','<','<','>','>'},                                                 {'<','<','<','<','<','=',' '},                                                 {'>','>','>','>',' ','>','='},                                                 {'<','<','<','<','<',' ','='}                                              };    int rows = operate.IndexOf(first);    int cols = operate.IndexOf(last);    return level[rows, cols];}

主要是來展示表中的內容,返回>,<,=.

算術運算式的計算演算法,參數假設為標準的中綴運算式,否則會出現異常

/// <summary>/// 算符優先演算法/// </summary>/// <param name="infixExpression">中綴運算式</param>/// <returns></returns>public int ComputeExpression(string infixExpression){    Stack<int> stackOperand = new Stack<int>();  //運算元棧    Stack<char> stackOperator = new Stack<char>(); //操作符棧    stackOperator.Push('#');  //作為棧空的結束符    infixExpression = infixExpression + "#"; //中綴運算式的結束符    int temp = 0;    int result = 0;    int count = 0;    char cur = infixExpression[count];        while (cur != '#' || stackOperator.Peek() != '#') //掃描完算術運算式,並且操作符棧為空白    {        if (cur == ' ') continue;        if (IsOperand(cur)) //運算元直接入棧        {            stackOperand.Push(Int32.Parse(cur.ToString()));            cur = infixExpression[++count]; //掃描算術運算式下一位        }        else        {            switch (Precede(stackOperator.Peek(), cur)) //比較操作符棧頂元素和掃描的當前算符的優先順序            {                    //當前運算子優先順序較大,則直接入棧,置於棧頂(優先順序高需先計算)                case '<':                    stackOperator.Push(cur);                    cur = infixExpression[++count];                    break;                    //等於則表示棧頂元素為左括弧,當前字元為右括弧                case '=':                    stackOperator.Pop();//彈出左括弧                    cur = infixExpression[++count];                    break;                    //當前運算子優先順序小,則彈出棧頂運算子並從運算元棧彈出兩個運算元                case '>':                    temp = stackOperand.Pop();                    result = stackOperand.Pop();                    //注意計算的順序,計算結果入運算元棧,並且繼續比較新的棧頂操作符和當前操作符的優先順序                    stackOperand.Push(Operate(result, temp, stackOperator.Pop()));                    break;            }        }    }        return stackOperand.Peek();}

以上方法是直接接受中綴運算式來計算結果,在應用方面有

計算機(更多的操作符,而且不一定都是二目運算子),相信也不難擴充

過濾方法(一般論壇的過濾演算法都是framework中的contains方法),contains方法只能為(s1and s2 and s3…),算符優先演算法則可以 (  s1and s2) or (s3) ) and s4等一系列的負責運算式

算符優先演算法還有一種是  先將標準的中綴運算式轉換為尾碼運算式(逆波蘭式),然後用一個用來儲存計算結果的棧來實現逆波蘭式計算。

不詳講

public string InfixToPostfix(string infixExpression){    Stack<char> stackOperand = new Stack<char>(); //運算元    Stack<char> stackOperator = new Stack<char>(); //運算子    for (int i = 0; i < infixExpression.Length; i++)    {        if (infixExpression[i] == ' ') continue;        char oper = infixExpression[i];        switch (oper)        {            case '+':            case '-':                while (stackOperator.Count > 0)                {                    char ch = stackOperator.Peek();                    if (GetOperatorPriority('-') <= GetOperatorPriority(ch))                    {                        stackOperator.Pop();                        stackOperand.Push(ch);                    }                    else                    {                        break;                    }                }                stackOperator.Push(oper);                break;            case '*':            case '/':                while (stackOperator.Count > 0)                {                    char ch = stackOperator.Peek();                    if (GetOperatorPriority('*') <= GetOperatorPriority(ch))                    {                        stackOperator.Pop();                        stackOperand.Push(ch);                    }                    else                    {                        break;                    }                }                stackOperator.Push(oper);                break;            case '(':                stackOperator.Push(oper);                break;            case ')':                while (stackOperator.Count > 0 && stackOperator.Peek() != '(')                {                    char ch = stackOperator.Pop();                    stackOperand.Push(ch);                }                stackOperator.Pop();                break;            default:                stackOperand.Push(oper);                break;        }    }    while (stackOperator.Count > 0)    {        stackOperand.Push(stackOperator.Pop());    }    StringBuilder sb = new StringBuilder();    for (int i = stackOperand.Count; i > 0; i--)    {        sb.Insert(0, stackOperand.Pop());    }    return sb.ToString();}

public int ComputeArithmeticExpression(string postfixExpression) {    Stack<int> stackResult = new Stack<int>();    int result = 0;    int temp = 0; //     for (int i = 0; i < postfixExpression.Length; i++)    {        char expr = postfixExpression[i];        switch (expr)        {            case '+':                result = stackResult.Pop() + stackResult.Pop();                stackResult.Push(result);                break;            case '-':                temp = stackResult.Pop();                result = stackResult.Pop() - temp;                stackResult.Push(result);                break;            case '*':                result = stackResult.Pop() * stackResult.Pop();                stackResult.Push(result);                break;            case '/':                temp = stackResult.Pop();                result = stackResult.Pop() / temp;                break;            default:                stackResult.Push(Int32.Parse(expr.ToString()));                break;        }    }    result = stackResult.Pop();    return result;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.