求一个包加减乘除和小括号的字符串的结果

解题思路和代码原型来源于牛课网, 我自己实现了一遍,添加了部分注释

  1 package problems_2016_08_10;
  2
  3 import java.util.LinkedList;
  4 /*
  5 总述:
  6 一共有五个函数分别是:
  7
  8                     getvalue():
  9                           参数:待求的字符串、
 10                           作用:一个启动函数,调用value函数
 11                           返回值:返回value函数返回值的第一个参数,就是求出的值
 12
 13                     value():
 14                           参数:总的待求的字符串,从哪一个位置开始求
 15                           作用:这个函数只是可以求不加小括号的情况。
 16                                   在这种情况下,把数字和加减乘除放进que双端链表中,并且在放的时候用addnum方法,将乘除处理掉,只剩加减和数字,再将que链表通过getnum方法求出具体的值,返回给上一层。
 17                                   因为不能处理小括号,所以碰见小括号就将括号里面的内容抛给下一层递归(value函数)。
 18                                   这个value函数只有当发现右括号就停止
 19                           返回值:value函数在返回求出的结果的时候,还要返回处理的右括号的位置的索引值
 20                     addnum()
 21                           参数:que双端链表(这个是在value函数里面定义的),一个待添加进来的数字(value里面的pre)
 22                           作用:将字符串中紧挨的数字(表示是一个多位数字)转化为一个数字,并且将他加入到que中,在加入时处理掉que中的乘除号
 23                           返回值:没有返回值。因为是在value内部调用的,将当层递归的que变成了只包含加减和数字的字符
 24
 25                     getnum()
 26                           参数:只包含加减和数字的que
 27                           作用:将只包含加减和数字的que求出结果
 28                           返回值:返回的是每一层小括号中(也是每一层递归当中)的结果
 29                     main()
 30                           用来进行检测代码功能的函数
 31
 32
 33 */
 34 public class ExpressionCompute {
 35
 36     public static int getValue(String str) {
 37         return value(str.toCharArray(), 0)[0];
 38     }
 39
 40     public static int[] value(char[] str, int i) {
 41         LinkedList<String> que = new LinkedList<String>();
 42         int pre = 0;
 43         int[] bra = null;
 44         while (i < str.length && str[i] != ‘)‘) {//如果i(当前操作位置)还没有到达最有端,并且还没有碰到右边的括号,那就继续执行这个递归函数
 45             if (str[i] >= ‘0‘ && str[i] <= ‘9‘) {//如果当前操作的是两个运算符号之间的数字
 46                 pre = pre * 10 + str[i++] - ‘0‘;//将字符串格式的数字转换为int,减‘0‘相当于减了这个字符的ascii码的值,字符串就变成数字了
 47             } else if (str[i] != ‘(‘) {//如果发现也没有碰到了左括号,那说明碰到的是运算符
 48                 addNum(que, pre);//这个函数的功能是在pre加入que时看一下que的最后一个字符(肯定是运算符)是否为乘除,是的话进行结算
 49                 que.addLast(String.valueOf(str[i++]));//在上面获取到结算的结果加入之后下一位肯定是运算符,也加入
 50                 pre = 0;//把pre(用来存放两个运算符之间的数值的变量)清零
 51             } else {//说明遇到左括号里
 52                 bra = value(str, i + 1);//碰到了左括号,那么就调用这个函数本身,将左括号之后的内容加入到内层递归中(传入的是左括号的下一个位置的索引)
 53                 pre = bra[0];//value函数返回一个数组(第29行)   第一个参数为处理过的值
 54                 i = bra[1] + 1;//第二个是处理到的值,+1表示下次开始处理的位置
 55             }
 56         }
 57         addNum(que, pre);//最后没有遇到加减乘除  所以还要再来一次addnum
 58         return new int[] { getNum(que), i };//返回这一层递归中的值和 处理到的位置i
 59     }
 60
 61     public static void addNum(LinkedList<String> que, int num) {//这个函数的作用可以看成和que.addLast类似,que.addLast是直接把符号插入到que中需要用到的方法,当时当你想插入数字时需要看一下前一个符号的情况,所以自己封装了一个稍微复杂点儿的类似的方法
 62         if (!que.isEmpty()) {//判断是否为空
 63             int cur = 0;
 64             String top = que.pollLast();//先弹出一个
 65             if (top.equals("+") || top.equals("-")) {
 66                 que.addLast(top);//如果之前是加减,直接把这个数字放进去就可以了
 67             } else {//如果之前的符号为乘除,那需要运算之后才能放入(保证que里面始终只放加减符号和数字)
 68                 cur = Integer.valueOf(que.pollLast());//再弹出一个
 69                 num = top.equals("*") ? (cur * num) : (cur / num);//将第二次弹出的(肯定是一个数字,由19  20行可知)
 70             }
 71         }
 72         que.addLast(String.valueOf(num));//为空的话直接插入num,不为空让算出的结果等于num,好巧妙,又省了几行代码
 73     }
 74
 75     public static int getNum(LinkedList<String> que) {//getnum的方法的作用仅仅是求一个只包含加减和数字的数组,的运算结果
 76         int res = 0;//用来保存结果
 77         boolean add = true;//用来描述一种状态,其实就是区分加减
 78         String cur = null;//用来存放每次新的pollFirst()出来的值(是string类型的)
 79         int num = 0;//用来保存cur转换回来的num类型
 80         while (!que.isEmpty()) {//判断que里面是不是空的
 81             cur = que.pollFirst();//弹出双向列表第一个
 82             if (cur.equals("+")) {//如果弹出的是加号
 83                 add = true;//将add设置为true,用于下一个检测到数字的时候使用
 84             } else if (cur.equals("-")) {//如果弹出的是减号
 85                 add = false;//将add设置为false,用于下一个检测到数字的时候使用
 86             } else {//如果不为加减那么肯定就是数字了
 87                 num = Integer.valueOf(cur);//将字符类型的准换成数字类型
 88                 res += add ? num : (-num);//res+=(+num或者-num),三目运算符大大减少代码数量
 89             }
 90         }
 91         return res;//返回最后求出的结果
 92     }
 93
 94     public static void main(String[] args) {//进行一些测试
 95         String exp = "48*((70-65)-43)+8*1";
 96         System.out.println(getValue(exp));
 97
 98         exp = "4*(6+78)+53-9/2+45*8";
 99         System.out.println(getValue(exp));
100
101         exp = "10-5*3";
102         System.out.println(getValue(exp));
103
104         exp = "-3*4";
105         System.out.println(getValue(exp));
106
107         exp = "3+1*4";
108         System.out.println(getValue(exp));
109
110     }
111
112 }
时间: 2024-11-08 21:57:50

求一个包加减乘除和小括号的字符串的结果的相关文章

表达式求值(只包括小括号)

表达式求值 前缀式:就是将操作符放到数值的前面:如:a+b :  +ab: 中缀式:就是将操作符放在数值中间,其实就是我们平时生活中所写的正常的表达式.如:a+b: 后缀式:就是将操作符放在数值的后面,比如:a+b:——ab+. 对于表达式求值,最简单的当然是对后缀表达式(也称为逆波兰式)进行求值了. 而我们生活中所写的运算表达式,一般都是中缀表达式.但是我们计算的时候用到的却是后缀表达式.这就需要我们首先将中缀表达式转换为后缀表达式,然后再进行运算了. 1.中缀式转换为后缀式 下面是将中缀式(

模拟计算器:一个带加减乘除和括号的表达式 求值

//整数,加,减,乘,除,多重小括号表达式的求值,例如 -1+(2-(3+4)/7)*5,(不带输入检查): #include <sstream> #include <iostream> #include <string> using namespace std; int sToI(string s); string iToS(int myInt); string sCalculate(string s1, string s2, char opr); string no

使用eval()将json字符串转换为对象要多加一个小括号

使用eval()将json字符串转换为对象要多加一个小括号:关于eval()函数的具体用法这里就不多介绍了,具体可以参阅javascript的eval()方法一章节,下面就介绍一下为什么使用eval()函数将json格式字符串转换为对象的时候,需要多嵌套一层小括号,下面就介绍一下它的原因,希望能够对需要的朋友带来帮助.先看一段转换代码: var jsonStr='{"webName":"蚂蚁部落","webAddress":"青岛市南区

编写一个程序,用户输入两个数,求出其加减乘除,并用消息框显示计算结果

编写一个程序,用户输入两个数,求出其加减乘除,并用消息框显示计算结果 import javax.swing.JOptionPane; public class Test{ public static void main(String[] args) { int n1=Integer.parseInt(JOptionPane.showInputDialog("Input number 1: ")); int n2=Integer.parseInt(JOptionPane.showInpu

正则学习三 (小括号作用)

var reg=/^18|19$/ //结果可匹配:18,19, 189, 119, 819,181, 1819 意思为: *18或者19 *以18开头或以19结尾, *以1开头,9结尾,当中包含8或1 var reg=/^(18|19)$/ //结果:18, 19 //():正则中的分组,也可以理解为一个大正则中的一个小正则(包起来部分是一个整体),在正则中可以使用小括号改变一些默认优先级//小分组第二个作用:分组引用//小分组第三个作用:分组捕获 //分组引用:\1或\2...出现和第n个分

包你说小程序开发语音红包app定制

小程序口令红包系统 小程序口令红包模式 (杨生137,9454,9329 微电) 包你说红包小程序系统软件  小程序包你说红包系统模式  包你说红包小程序 小程序口令网站  包你说红包微信小程序  包你说红包口令小程序 小程序包你说红包系统开发 1.营销活动多样性.并可开展基于粘性维护的活动跨界营销.会员积分.互动抽奖.红包.优惠等线上线下活动,并能通过连续扫码.会员积分.连续签到 等进行累积扫码,用于对消费者的粘性维护 2.实时调整营销策略,提升活动效率活动可根据产品.时间.地点快速部署.实时

小易邀请你玩一个数字游戏,小易给你一系列的整数。你们俩使用这些整数玩游戏。每次小易会任意说一个数字出来,然后你需要从这一系列数字中选取一部分出来让它们的和等于小易所说的数字。 例如: 如果{2,1,2,7}是你有的一系列数,小易说的数字是11.你可以得到方案2+2+7 = 11.如果顽皮的小易想坑你,他说的数字是6,那么你没有办法拼凑出和为6 现在小易给你n个数,让你找出无法从n个数中选取部分求和

小易邀请你玩一个数字游戏,小易给你一系列的整数.你们俩使用这些整数玩游戏.每次小易会任意说一个数字出来,然后你需要从这一系列数字中选取一部分出来让它们的和等于小易所说的数字. 例如: 如果{2,1,2,7}是你有的一系列数,小易说的数字是11.你可以得到方案2+2+7 = 11.如果顽皮的小易想坑你,他说的数字是6,那么你没有办法拼凑出和为6 现在小易给你n个数,让你找出无法从n个数中选取部分求和的数字中的最小数. 输入描述: 输入第一行为数字个数n (n ≤ 20) 第二行为n个数xi (1

python:元组和小括号的误导

书上说元组就是被包含在小括号里面,不能被修改.列表是包含在中括号里面,可以被修改. 列表中可以嵌套列表,元组中可以嵌套元组,一般没人混用,这点测试无误: >>> aa[0] (12, 34) >>> aa[0]=(1,2) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does n

js面向对象编程:两个小括号的使用

在查看很多jQuery的过程中,经常遇到两个小括号的情况. 例如: (function() { alert("测试1"); })(); (function() { alert("测试3"); }()); 其实这段代码,就是定义了一个匿名函数,并且进行了调用, 相当于如下几行代码: (function ListCommon2() { alert("测试1"); })(); (function ListCommon3() { alert("