首页 > 代码库 > 逆波兰式篇(后缀表达式)

逆波兰式篇(后缀表达式)

一、逆波兰表示法Reverse Polish notationRPN,或逆波兰记法),是一种数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面。也称为后缀表达式。

二、一般算法

将一个普通的中序表达式转换为逆波兰表达式的一般算法是:

  1.  首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
  2.  读入一个中缀表达式,为了方便起见,可在其最右端追加一个最低优先级运算符(如:#号)。(这样做的目的是,最后读入#号运算符时将运算符栈中所有运算符都输        出)。
  3.  从左至右扫描该中缀表达式,如果当前字符是数字,则分析到该数字串的结束,并将该数字串直接输出。
  4.  如果不是数字,该字符则是运算符,此时需比较该运算符与运算符栈顶运算符的优先关系:
  5.   (1)、若该运算符优先级高于栈顶运算符优先级别(或栈为空),则直接将该运算符压入运算符栈中;
  6.   (2)、若该运算符优先级小于或等于此运算符栈顶的运算符,则弹出栈顶运算符并输出,重复比较、输出,直到栈为空或该运算符优先级高于栈顶运算符,然后将该运算  符入栈。
  7.  重复上述操作(3)-(4)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,输出结果便是中缀表达式转化为逆波兰表示的简单算术表达式。

三、举例说明

  例如中缀表达式:9+(3-1) X 3+10+2,其实是我们人类所理解的四则表达运算式,现在我们将其转为机器方便识别的后缀表达式。

四、算法实现

namespace Eduii.Practice.StackDemo{    /*     * 词汇:     *  postfix expression 后缀表达式     *  infix expression   中缀表达式     *  prefix expression  前缀表达式      *      */    /*     *分析:     *目前四则运算符包括:(、)、+、-、*、/、%     * 优先级:     *      1、* 、/、%     *      2、+ 、-     *      3、(     *      4、)     *      */    /*     *拓展:      *    1、字符串包含其他字符的判断     *    2、四则运算非个位时     *    3、包含小数点     *    4、包含正负号     *    5、......     */    /*     *参考文档     *  http://www.cnblogs.com/mygmh/archive/2012/10/06/2713362.html     *  http://www.nowamagic.net/librarys/veda/detail/2307     *  http://www.cnblogs.com/stay-foolish/archive/2012/04/25/2470590.html     */    /// <summary>    /// 逆波兰式的算法实现    /// </summary>    public class RPExpression    {        /// <summary>        ///  使用字符串存储        /// </summary>        /// <param name="infixExpression"></param>        /// <returns></returns>        /*         *从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后         *缀表达式的一部分;若是符号,若为‘(’,直接压入操作栈,         *若为其他字符则判断其与栈顶符号的优先级,是右括号或优先级低         *于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出, 并将当前符号进栈,一直         *到最终输出后缀表达式为止。          *          */        public string Convert2PostfixExpWithString(string infixExpression)        {            //后缀表达式            string postfixExp = string.Empty;            //先处理空格            if (string.IsNullOrWhiteSpace(infixExpression))                return postfixExp;            //去除空格            infixExpression = infixExpression.Trim();            //操作栈            Stack<char> operatorStack = new Stack<char>();            //四则表达式长度            int length = infixExpression.Length;            //临时存储字符            char temp;            //数字            string digital = string.Empty;            for (int i = 0; i < length; i++)            {                temp = infixExpression[i];                bool isOperator = IsOperator(temp);                if (isOperator)                {                    if (!string.IsNullOrWhiteSpace(digital))                    {                        postfixExp += string.Format("{0},", digital);                        digital = string.Empty;                    }                    if (temp == ‘(‘)                        operatorStack.Push(temp);                    //判断是否为‘(‘                    else if (temp == ‘)‘)                    {                        //当为‘)’时,直接取出栈顶的元素,直到第一个‘(‘为止                        char topElement = operatorStack.Pop();  //返回栈顶元素当不将其移除                        while (topElement != ‘(‘)                        {                            postfixExp += string.Format("{0},", topElement);                            if (operatorStack.Count == 0)                                break;                            topElement = operatorStack.Pop();                        }                    }                    else                    {                        //栈为空时直接插入当前运算符                        if (operatorStack.Count == 0)                            operatorStack.Push(temp);                        //栈中存在操作符时要判断优先级                        else                        {                            char topElement = operatorStack.Peek();                            while (topElement != ‘#‘)                            {                                if (ComparePriority(temp, topElement) > 0)                                {                                    operatorStack.Push(temp);                                    topElement = ‘#‘;                                }                                else                                {                                    //当前栈顶出栈                                    postfixExp += string.Format("{0},", topElement);                                    operatorStack.Pop();                                    if (operatorStack.Count != 0)                                        topElement = operatorStack.Peek();                                    else                                    {                                        operatorStack.Push(temp);                                        topElement = ‘#‘;                                    }                                }                            }                        }                    }                }                else                {                    //数字拼接                    digital += temp;                    //直接输出数字                    if (i == length - 1)                    {                        postfixExp += string.Format("{0},", digital);                    }                }            }            //输出所有的操作            while (operatorStack.Count > 0)            {                postfixExp += string.Format("{0},", operatorStack.Pop());            }            return postfixExp;        }        //比较优先级        private int ComparePriority(char ch1, char ch2)        {            int ch1Pri = GetPriority(ch1);            int ch2Pri = GetPriority(ch2);            return ch1Pri - ch2Pri;        }        //获得字符优先级        private int GetPriority(char ch)        {            switch (ch)            {                case ‘(‘:                    return -1;                case ‘+‘:                case ‘-‘:                    return 0;                case ‘*‘:                case ‘/‘:                case ‘%‘:                    return 1;                default:                    throw new Exception("未定义操作符.");            }        }        // 判断字符是否为操作符        private bool IsOperator(char ch)        {            if (ch == ‘+‘ || ch == ‘-‘ || ch == ‘*‘ || ch == ‘/‘ || ch == ‘%‘ || ch == ‘(‘ || ch == ‘)‘)                return true;            return false;        }        /// <summary>        /// 计算后缀表达式值        /// </summary>        /// <param name="expression"></param>        /// <returns></returns>        /*         *从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符         *号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈, 一直到最终获得结果。          */        public decimal CalculatePostfixExp(string expression)        {            if (string.IsNullOrWhiteSpace(expression))                return 0;            //清除空格            expression = expression.Trim();            //数据            decimal digigtal = 0;            //取得后缀表达式中的字符            int i = 0;            char topElement = expression[i];            Stack<decimal> dataStack = new Stack<decimal>();            while (topElement != ‘#‘)            {                if (topElement != ‘,‘)                {                    if (IsOperator(topElement))                    {                        //取出栈顶元素进行运算                        decimal num1 = dataStack.Pop();                        decimal num2 = dataStack.Pop();                        decimal result = Calculate(num2, num1, topElement);                        dataStack.Push(result);                    }                    else                    {                        int singleDigit = topElement - 48;                        if (digigtal != 0)                            digigtal = digigtal * 10 + singleDigit;                        else                            digigtal = singleDigit;                    }                }                else                {                    if (digigtal != 0)                    {                        dataStack.Push(digigtal);                        digigtal = 0;                    }                }                if (i == expression.Length - 1)                    break;                i++;                topElement = expression[i];            }            return dataStack.Pop();        }        //两数相加        private decimal Calculate(decimal num1, decimal num2, char ope)        {            switch (ope)            {                case ‘+‘:                    return num1 + num2;                case ‘-‘:                    return num1 - num2;                case ‘*‘:                    return num1 * num2;                case ‘/‘:                    return num1 / num2;                default:                    throw new ApplicationException("未定义的数据类型.");            }        }    }}

  

逆波兰式篇(后缀表达式)