算法-表达式求值

今天在网上看到Dijkstra双栈算术表达式求值算法,可以用来实现计算器类型的app,以前很早的时候知道通过算术栈和数值栈搞定的,这次用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];
}

还有很多缺憾,比如不能处理浮点数,不能处理,不能处理超过两位数的整数,如果有想法的可以继续优化一下~

时间: 2024-08-06 19:49:28

算法-表达式求值的相关文章

数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚,所以很多需要自己揣摩.这也体现了算法和程序设计语言的特点,算法更侧重本质的描述,而任何编程语言都要照顾到实现的细节以及数据类型等语法方面的需求. 表达式求值: [编码中....] 二.头文件 迷宫求解: 1 //3_2_maze.h 2 /** 3 author:zhaoyu 4 email:[em

表达式求值及转换算法

后缀表达式求值算法 stack operands;  //运算数栈 while(没到表达式尾) {     scanf("一个运算对象op");     if(op is 运算数)         operands.push(op);     else if(op is 运算符)     {         operand_right = operands.pop();         operand_left = operands.pop();         result = op

算法手记(2)Dijkstra双栈算术表达式求值算法

这两天看到的内容是关于栈和队列,在栈的模块发现了Dijkstra双栈算术表达式求值算法,可以用来实现计算器类型的app. 编程语言系统一般都内置了对算术表达式的处理,但是他们是如何在内部实现的呢?为了了解这个过程,我们可以自行搭建一套简易的算术表达式处理机制,这里就用到栈特性和本篇提到的Dijkstra算法. 概述:     算术表达式可能是一个数.或者是由一个左括号.一个算术表达式.一个运算符.另一个算术表达式和一个右括号组成的表达式.为了简化问题,这里定义的是未省略括号的算术表达式,它明确地

表达式求值算法、rpn、1470、1475、1477、1479

以下为表达式求值系列完整算法,借用C++语言,读者不妨对照下图表达式求值算法实例,仔细推敲. 1 /* 2 DATA:2015 1 30 3 From:13420228 4 */ 5 //测试数据: 6 // 4 7 // (0!+1)*2^(3!+4) - (5! - 67 - (8+9)) 8 // (1+2)*3+4*5 9 // 1.000 + 2 / 4 10 // ((1+2)*5+1)/(4^2)*3 11 #include <iostream> 12 #include <

【算法】E.W.Dijkstra算术表达式求值

算术表达式求值 我们要学习的一个栈的用例同时也是展示泛型的应用的一个经典例子,就是用来计算算术表达式的值,例如 ( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) ) 如果将4乘以5,把3加上2,取它们的积然后加上1,就得到了101.但Java系统是如何完成这些运算的呢?不需要研究Java系统的构造细节,我们也可以编写一个Java程序来解决这个问题.它接受一个输入字符串(表达式)并输出表达式的值.为了简化问题,首先来看一下这份明确的递归定义:算术表达式可能是一个数,或者是由一个左括号

使用E.W.D.Dijkstra设计算法实现算数表达式求值

要求:编程模拟(1+(2+3)*(4*5))的运算过程,重点在于如何解析由括号运算符和数字组成的字符串,并按照正确的顺序完成各种初级运算符的操作. 实现思路:用两个栈(LIFO)结构来实现(一个用于保存运算符,一个用于保存操作数) 将操作数压如操作数栈 将操作符压如操作符栈 忽略左括号 在遇到右括号时,弹出一个运算符,并弹出所需数量的操作数,并将操作符和操作数的运算结果压到操作数栈 1 package com.luochuang.demo.stdlib; 2 3 public class Eva

表达式求值相关算法

实现对一个数学表达式的求值,例如:1+2*(3+4) 这个表达式的值为 15 这个问题主要要分为如下几个步骤: 语法分析: 将字符串表达式转化为数字和操作符的 token 数组,['1', '+', '2', '*', '(', '3', '+', '4', ')'] 转逆波兰表达式: 将中缀表达式转后缀表达式,['1', '2', '3', '4', '+', '*', '+'] 逆波兰表达式求值: 15 逆波兰表达式转二叉树: 条件表达式中,二叉树的求值能提前返回,能比逆波兰表达式计算量更少

JAVA-栈实现中序表达式求值

中序表达式对我们而言是很直观的(我们平时接触的就是这个),但计算机处理起来比较麻烦(括号.优先级之类的),前序和后序表达式中没有括号,而且在计算中只需单向扫描,不需要考虑运算符的优先级.如2*3/(2-1)+3*(4-1) 前序表达式就是前缀表达式,不含括号的算术表达式,而且它是将运算符写在前面,操作数写在后面的表达式,例如:+/*23-21*3-4,也称为"波兰式". 后序表达式与前序表达式扫描方式正好相反,例如:23*21-/341-*+. 用两个栈实现中序表达式求值,表达式中只支

page80-栈用例-算术表达式求值

表达式由括号, 运算符和操作数(数字)组成.我们根据以下4中情况从左到右逐个将这些实体送入栈处理. (1)将操作数压入操作数栈: (2)将运算符压入运算符栈: (3)忽略左括号: (4)在遇到右括号时, 弹出一个运算符,弹出所需数量的操作符,并将运算符和操作符的运算结果压入操作数栈. [地杰斯特拉的双栈算术表达式求值算法] public class Evaluate { public static void main(String[] args) { Stack<String> ops = n