今天在網上看到Dijkstra的雙棧算術表達式求值算法,以前很早的時候知道通過算術棧和數值棧搞定的,這次用OC通過數組實現了預期的效果.
(原理參考網上,原作者不詳)
編程語言系統一般都內置了對算術表達式的處理,我們可以簡易的模仿一下算術表達式處理機制,思想不變,主要是實現方式略有不同。算術表達式可能是一個數、或者是由一個左括號、一個算術表達式、一個運算符、另一個算術表達式和一個右括號組成的表達式。為了簡化問題,這里定義的是未省略括號的算術表達式,它明確地說明了所有運算符的操作數,形式如下:(1+((2+3)*(4*5)))
思路:
表達式由括號、運算符和操作數構成,我們根據以下4中情況從左至右逐個將這些實體送入棧處理:
1.將操作數壓入操作數棧;
2.將運算符壓入運算符棧;
3.忽略左括號;
4.在遇到右括號時,彈出一個運算符,彈出所需數量的操作數,並將運算后的結果壓入操作數棧;
在處理完最后一個右括號時,操作數棧上只會剩下一個值,它就是表達式的計算結果。這種方法咋一看難理解,但要證明它能計算得到正確的值很簡單:
每當算法遇到一個括號包圍,並由一個運算符和兩個操作數組成的子式時,他都將運算符和操作數運算結果壓入操作數棧。這樣的結果就像是在輸入中用這個值代替了該子表達式,因此用這個值代替子表達式得到的結果和原表達式相同。我們可以反復應用這個規律並得到一個最終值。
例如:
(1+((2+3)*(4*5)))
(1+(5*(4*5)))
(1+(5*20))
(1+100)
101
OC代碼實現如下:
-(NSInteger)operationExpression:(NSString *)expression{ NSMutableArray *operationArr=[[NSMutableArray alloc]initWithCapacity:1]; NSMutableArray *valArr=[[NSMutableArray alloc]initWithCapacity:1]; for (NSInteger i=0; i<expression.length; i++) { NSString *currentStr=[NSString stringWithFormat:@"%c",[expression characterAtIndex:i]]; if([currentStr isEqualToString:@"("]); else if([currentStr isEqualToString:@"+"]){ [operationArr addObject:currentStr]; }else if([currentStr isEqualToString:@"-"]){ [operationArr addObject:currentStr]; }else if([currentStr isEqualToString:@"*"]){ [operationArr addObject:currentStr]; }else if([currentStr isEqualToString:@")"]){ NSInteger lastValue=[[valArr objectAtIndex:valArr.count-1] integerValue]; NSInteger secondValue=[[valArr objectAtIndex:valArr.count-2] integerValue]; [valArr removeObjectAtIndex:valArr.count-1]; [valArr removeObjectAtIndex:valArr.count-1]; NSString *lastOperation=[operationArr objectAtIndex:operationArr.count-1]; [operationArr removeObjectAtIndex:operationArr.count-1]; NSInteger newValue=0; if([lastOperation isEqualToString:@"+"]) newValue=secondValue+lastValue; else if([lastOperation isEqualToString:@"-"]) newValue=secondValue-lastValue; else if([lastOperation isEqualToString:@"*"]) newValue=secondValue*lastValue; else if([lastOperation isEqualToString:@"/"]) newValue=secondValue/lastValue; [valArr addObject:[NSNumber numberWithLong:newValue]]; }else{ [valArr addObject:currentStr]; } } return [[valArr objectAtIndex:0] integerValue]; }
還有很多缺憾,比如不能處理浮點數,不能處理,不能處理超過兩位數的整數,如果有想法的可以繼續優化一下~