[算法 笔记]字符串表达式计算(简易版)
題目:編寫一個(gè)函數(shù),計(jì)算字符串中表達(dá)式的值,參數(shù)中只包含計(jì)算符:+,-,*,/等。例如,str=”10+50+2*6/3”,result=64。
解析:
考慮算術(shù)表達(dá)式計(jì)算規(guī)則:
利用兩個(gè)輔助棧來(lái)存儲(chǔ)結(jié)果。一個(gè)用于存儲(chǔ)數(shù)值,一個(gè)用于存儲(chǔ)操作符。考慮算術(shù)表達(dá)式的計(jì)算過(guò)程(從左往右計(jì)算,先計(jì)算高優(yōu)先級(jí)操作符),因此表達(dá)式字符串逆序壓入棧中。由于考慮棧存儲(chǔ)的特點(diǎn)以及計(jì)算表達(dá)式的順序問(wèn)題,需要逆序的將數(shù)值和算術(shù)符壓入到棧中。因此,需要首先將數(shù)值逆序,然后在將整個(gè)表達(dá)式逆序。
考慮操作符優(yōu)先級(jí)的處理問(wèn)題:在計(jì)算過(guò)程將出現(xiàn)三種情況(用current_opr表示剛剛從棧中彈出的操作符,top_opr表示操作符棧中棧頂?shù)牟僮鞣?#xff09;:
在上述三種情況中,第一種和第二種均情況不需要考慮,直接計(jì)算直到current_opr的優(yōu)先級(jí)低于top_opr的優(yōu)先級(jí)。
現(xiàn)在來(lái)討論第三種情況的處理過(guò)程,將current_opr從棧頂開始向棧底“冒泡”,一直到操作符的優(yōu)先級(jí)等于current_opr才停止。在操作符移動(dòng)的過(guò)程中,數(shù)值棧中的元素也需要進(jìn)行同方向的“冒泡”處理,但是深度要比操作符多一個(gè)。因?yàn)槟壳翱紤]的操作符均是二元操作符,需要兩個(gè)操作數(shù)來(lái)完成計(jì)算。
例如,算式字符串為:”25?+?10*50*12”。遍歷的結(jié)果為:
數(shù)值棧:(digit_stack,value_top=3)
| 12 | 50 | 10 | 25 | ? | ? |
操作符棧:(op_stack,opr_top=1)
| ‘*’ | ‘*’ | ? | ? | ? | ? |
處理過(guò)程:由于current_opr?=?‘+’,top_opr=’*’,priority(current_opr)?<?priority(top_opr),因此需要對(duì)current_opr操作符進(jìn)行“冒泡”處理,一直到優(yōu)先級(jí)與current_opr相同為止。
調(diào)整后,數(shù)值棧:(digit_stack,value_top=3)
| 25 | 12 | 50 | 10 | ? | ? |
調(diào)整后,操作符棧為:(op_stack,opr_top=1)
| ‘+’ | ‘*’ | ? | ? | ? | ? |
當(dāng)前,current_opr=’*’,top_opr=’*’,則priority(current_opr)?==?priority(top_opr),即符號(hào)第一種情況。
在編程中,對(duì)于“冒泡”處理有兩種形式:
1.?首先將元素壓入棧中,然后通過(guò)交換的形式來(lái)達(dá)到“冒泡”處理。
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.?不將數(shù)值壓入棧中,而是首先查找符合要求的“位置”,然后將元素插入。
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 = '\0'; 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?
簡(jiǎn)易版本不足之處:
轉(zhuǎn)載于:https://www.cnblogs.com/life91/p/3401993.html
總結(jié)
以上是生活随笔為你收集整理的[算法 笔记]字符串表达式计算(简易版)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: pyvex 的正确安装方式
- 下一篇: 给自己的Unity添加声音文件