今天在網上看到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];
}
還有很多缺憾,比如不能處理浮點數,不能處理,不能處理超過兩位數的整數,如果有想法的可以繼續優化一下~
