日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[算法 笔记]字符串表达式计算(简易版)

發(fā)布時(shí)間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [算法 笔记]字符串表达式计算(简易版) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  題目:編寫一個(gè)函數(shù),計(jì)算字符串中表達(dá)式的值,參數(shù)中只包含計(jì)算符:+-*/等。例如,str=”10+50+2*6/3”,result=64

  解析:

  考慮算術(shù)表達(dá)式計(jì)算規(guī)則

  • ?同優(yōu)先級(jí)操作符之間,從左到右計(jì)算;
  • 高優(yōu)先級(jí)操作符的計(jì)算要早于低優(yōu)先級(jí)操作符的計(jì)算;
  • 加減操作符優(yōu)先級(jí)低于乘除操作符優(yōu)先級(jí);
  • 括號(hào)內(nèi)的算術(shù)表達(dá)式的優(yōu)先級(jí)高于括號(hào)外的乘除操作符的優(yōu)先級(jí)。
  •   利用兩個(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;:

  • current_opr的優(yōu)先級(jí)等于top_opr的優(yōu)先級(jí);
  • current_opr的優(yōu)先級(jí)大于top_opr的優(yōu)先級(jí);
  • current_opr的優(yōu)先級(jí)小于top_opr的優(yōu)先級(jí)。
  •   在上述三種情況中,第一種和第二種均情況不需要考慮,直接計(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_stackvalue_top=3

    12

    50

    10

    25

    ?

    ?

      操作符棧:(op_stackopr_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_stackvalue_top=3

    25

    12

    50

    10

    ?

    ?

      調(diào)整后,操作符棧為:(op_stackopr_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)易版本不足之處

  • 不能計(jì)算括號(hào)表達(dá)式
  • 對(duì)負(fù)數(shù)不能有效的處理
  • 不能有效計(jì)算大數(shù)
  • 對(duì)表達(dá)式中符號(hào)以及括號(hào)的合法性檢查
  • 轉(zhuǎn)載于:https://www.cnblogs.com/life91/p/3401993.html

    總結(jié)

    以上是生活随笔為你收集整理的[算法 笔记]字符串表达式计算(简易版)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。