zoukankan      html  css  js  c++  java
  • [算法 笔记]字符串表达式计算(简易版)

      题目:编写一个函数,计算字符串中表达式的值,参数中只包含计算符:+-*/等。例如,str=”10+50+2*6/3”,result=64

      解析:

      考虑算术表达式计算规则

    1.  同优先级操作符之间,从左到右计算;
    2. 高优先级操作符的计算要早于低优先级操作符的计算;
    3. 加减操作符优先级低于乘除操作符优先级;
    4. 括号内的算术表达式的优先级高于括号外的乘除操作符的优先级。

      利用两个辅助栈来存储结果。一个用于存储数值,一个用于存储操作符。考虑算术表达式的计算过程(从左往右计算,先计算高优先级操作符),因此表达式字符串逆序压入栈中。由于考虑栈存储的特点以及计算表达式的顺序问题,需要逆序的将数值和算术符压入到栈中。因此,需要首先将数值逆序,然后在将整个表达式逆序。

      考虑操作符优先级的处理问题:在计算过程将出现三种情况(用current_opr表示刚刚从栈中弹出的操作符,top_opr表示操作符栈中栈顶的操作符):

    1. current_opr的优先级等于top_opr的优先级;
    2. current_opr的优先级大于top_opr的优先级;
    3. current_opr的优先级小于top_opr的优先级。

      在上述三种情况中,第一种和第二种均情况不需要考虑,直接计算直到current_opr的优先级低于top_opr的优先级。

      现在来讨论第三种情况的处理过程,将current_opr从栈顶开始向栈底“冒泡”,一直到操作符的优先级等于current_opr才停止。在操作符移动的过程中,数值栈中的元素也需要进行同方向的“冒泡”处理,但是深度要比操作符多一个。因为目前考虑的操作符均是二元操作符,需要两个操作数来完成计算。

      例如,算式字符串为:”25 + 10*50*12”。遍历的结果为:

      数值栈:(digit_stackvalue_top=3

    12

    50

    10

    25

     

     

      操作符栈:(op_stackopr_top=1

    ‘*’

    ‘*’

     

     

     

     

      处理过程:由于current_opr = ‘+’,top_opr=’*’,priority(current_opr) < priority(top_opr),因此需要对current_opr操作符进行“冒泡”处理,一直到优先级与current_opr相同为止。

      调整后,数值栈:(digit_stackvalue_top=3

    25

    12

    50

    10

     

     

      调整后,操作符栈为:(op_stackopr_top=1

    ‘+’

    ‘*’

     

     

     

     

      当前,current_opr=’*’,top_opr=’*’,则priority(current_opr) == priority(top_opr),即符号第一种情况。

      在编程中,对于“冒泡”处理有两种形式:

      1. 首先将元素压入栈中,然后通过交换的形式来达到“冒泡”处理。

     1 for ( i = opr_top - 1; i > 0; --i )
     2 {
     3     if ( priority(op_stack[i]) < priority(op_stack[i-1]) )
     4         swap( op_stack, i, i - 1 );
     5     else
     6         break;
     7 } 
     8 
     9 for ( j = value_top - 1; j > i; --j )
    10 {
    11     swap( value_stack, j, j - 1 );
    12 }

      2. 不将数值压入栈中,而是首先查找符合要求的“位置”,然后将元素插入。

     1 for ( i = opr_top; i > 0; --i )
     2 {
     3     if ( priority(op_stack[j-1]) > priority(current_opr) )
     4         op_stack[j] = op_stack[j-1];
     5     else
     6         break;
     7 }
     8 op_stack[i] = current_opr;
     9 ++opr_top;
    10 
    11 for ( j = value_top; j > i; --j )
    12 {
    13     value_stack[j] = value_stack[j - 1];
    14 }
    15 value_stack[j] = result;
    16 ++value_top;

      完整程序的源码:

      1 #include <vector>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <iterator>
      5 #include <stdexcept>
      6 using namespace std;
      7 
      8 class stack_is_empty : public runtime_error
      9 {
     10 public:
     11     stack_is_empty( const string s )
     12     : runtime_error( s ){}
     13 };
     14 
     15 class divisor_is_zero: public runtime_error
     16 {
     17 public:
     18     divisor_is_zero( const string s )
     19     : runtime_error( s ) {}
     20 };
     21 
     22 
     23 /**< expression reversal */
     24 void expression_reversal( string &expr )
     25 {
     26     string::iterator iter = expr.begin();
     27     string::iterator tmp;
     28 
     29     while ( iter != expr.end() )
     30     {
     31         if ( *iter >= '0' && *iter <= '9' )
     32         {
     33             /**< value reversal */
     34             for ( tmp = iter; iter != expr.end()
     35                    && *iter >= '0' && *iter <= '9'; ++iter );
     36             reverse( tmp, iter );
     37         }
     38         else
     39             ++iter;
     40     }
     41 
     42     /**< expression reversal */
     43     reverse( expr.begin(), expr.end() );
     44 }
     45 
     46 /**< remove spaces of expression */
     47 void remove_space( string &orig_expr, string &expr )
     48 {
     49     string::iterator iter = orig_expr.begin();
     50 
     51     for ( ; iter != orig_expr.end() ; ++iter )
     52     {
     53         if ( *iter != ' ' )
     54             expr.push_back( *iter );
     55     }
     56 }
     57 
     58 /**< separation of value and operators. */
     59 void preprocess( string &orig_expr,
     60                 vector<int> &value_stack,
     61                 vector<char> &oper_stack )
     62 {
     63     string expr;
     64     remove_space( orig_expr, expr );
     65     expression_reversal( expr );
     66 
     67     string::iterator iter = expr.begin();
     68 
     69     while ( iter != expr.end() )
     70     {
     71         // push value into value_stack.
     72         if ( *iter >= '0' && *iter <= '9' )
     73         {
     74             int value = 0;
     75             while ( iter != expr.end()
     76                    && *iter >= '0' && *iter <= '9' )
     77             {
     78                 value *= 10;
     79                 value += ( *iter - '0' );
     80                 ++iter;
     81             }
     82 
     83             value_stack.push_back( value );
     84         }
     85         else
     86         {
     87             // push operator into oper_stack.
     88             oper_stack.push_back( *iter );
     89             ++iter;
     90         }
     91     }
     92 }
     93 
     94 /**< get priority of operator */
     95 int oper_priority( const char ch )
     96 {
     97     int flag = 0;
     98     if ( ch == '*' || ch == '/' )
     99         flag = 5;
    100 
    101     return flag;
    102 }
    103 
    104 /**< compute value with operator */
    105 int compute_value( int lhs, int rhs, char oper )
    106 {
    107     int value = 0;
    108     switch( oper )
    109     {
    110     case '+': value = lhs + rhs; break;
    111     case '-': value = lhs - rhs; break;
    112     case '*': value = lhs * rhs; break;
    113     case '/':
    114         if ( rhs == 0 )
    115             throw divisor_is_zero( "divisor is zero." );
    116         value = lhs / rhs;
    117         break;
    118     default: break;
    119     }
    120 
    121     return value;
    122 }
    123 
    124 /**< compute value  */
    125 int compute_expr( vector<int> &value, vector<char> &oper )
    126 {
    127     char current_oper = '';
    128     int current_value = 0;
    129 
    130     if ( value.empty() || oper.empty() )
    131     {
    132         throw stack_is_empty( "Stack is empty." );
    133         return -1;
    134     }
    135 
    136     while ( value.empty() == false
    137            && oper.empty() == false )
    138     {
    139         current_oper = oper.back(), oper.pop_back();
    140 
    141         if ( oper.empty()
    142             || oper_priority( current_oper ) >= oper_priority( oper.back() )  )
    143         {
    144             int lhs = value.back();
    145             value.pop_back();
    146             int rhs = value.back();
    147             value.pop_back();
    148             current_value = compute_value( lhs, rhs, current_oper );
    149             value.push_back( current_value );
    150         }
    151         else
    152         {
    153             /**< value and operators are moved to new place. */
    154             oper.push_back( current_oper );
    155             size_t last_index = oper.size() - 1;
    156             for ( ; last_index > 0; --last_index  )
    157             {
    158                 if ( oper_priority( oper[last_index - 1] )
    159                      <= oper_priority( current_oper ) )
    160                     break;
    161                 oper[last_index] = oper[last_index - 1];
    162             }
    163             oper[last_index] = current_oper;
    164 
    165             current_value = value.back();
    166             for ( size_t j = value.size() - 1;
    167                     j > last_index; --j )
    168             {
    169                 value[j] = value[j - 1];
    170             }
    171             value[last_index] = current_value;
    172         }
    173     }
    174 
    175     if ( oper.empty() )
    176     {
    177         current_value = value.front();
    178     }
    179 
    180     return current_value;
    181 }
    182 
    183 int main()
    184 {
    185     string str( " 50 - 20 + 5 * 6 / 2" );
    186     vector<int> value;
    187     vector<char> oper;
    188     int result = 0;
    189     preprocess( str, value, oper );
    190 
    191     result = compute_expr( value, oper );
    192     cout << result << endl;
    193 
    194     return 0;
    195 }
    ComputeExpression

      简易版本不足之处

    1. 不能计算括号表达式
    2. 对负数不能有效的处理
    3. 不能有效计算大数
    4. 对表达式中符号以及括号的合法性检查
  • 相关阅读:
    使用python3安装frida-tools出错
    xposed代码示例
    android studio3.4打jar包
    uiautomator代码例子--java
    Mac下不能成功打开uiautomatorviewer的问题解决
    mac下生成keystore
    Python杨辉三角算法
    Python迭代器:捕获Generator的返回值
    Python函数:一个简单的迭代
    Python参数组合
  • 原文地址:https://www.cnblogs.com/life91/p/3401993.html
Copyright © 2011-2022 走看看