题目:可怜的二柱子同学,老师又对他的自动出题系统提出了新的要求:
可以控制下列参数:
是否有乘除法;
是否有括号(最多可以支持十个数参与计算);
数值范围;
加减有无负数;
除法有无余数!
思路和关键步骤:
1.是否有乘除法;加减有无负数;除法有无余数!,依据输入的不同年级判断是否需要,例如一年级没有乘除法,只有六年级有负数,除法在三年级开始有余数。
2.是否有括号,根据二叉树实现,根据去括号法则:
假设待去括号的表达式为 (m1 op1 n1) op (m2 op2 n2) 这里m1、n1、m2、m2可能自身就是个表达式,也可能是数字,op、op1、op2为运算符
1、若op为'/',则 (m2 op2 n2)的括号必须保留;
2、若op为'*'或'-',如果op2为'+'或'-',则(m2 op2 n2)的括号必须保留;
3、若op为'*'或'/',如果op1为'+'或'-',则(m1 op1 n1)的括号必须保留;
4、 除此之外,去掉括号不影响表达式的计算顺序。
但是有bug(运算位数最大只能是8位),至今没有解决;
核心代码:
1 /** 2 * 生成二叉树 3 * 4 */ 5 public void createBTree(){ 6 TreeNode lchild = null, rchild = null, lnode, rnode; 7 8 if(num == 1){ 9 lchild = new TreeNode(String.valueOf(Ran.getNumber(Arithmetic.getLine())), null, null); 10 rchild = new TreeNode(String.valueOf(Ran.getNumber(Arithmetic.getLine())), null, null); 11 root = new TreeNode(String.valueOf(Ran.getOperator()), lchild, rchild); 12 } 13 else{ 14 int num1 = 0; 15 int n = getDeep() - 3; 16 boolean[] place = Ran.getChildPlace(num); 17 root = new TreeNode(String.valueOf(Ran.getOperator()), null, null); 18 opeList.add(root); 19 20 for(int i = 0; i < n; i++){ 21 for(int j = 0; j < (int)Math.pow(2, i); j++, num1++){ 22 lchild = new TreeNode(String.valueOf(Ran.getOperator()), null, null); 23 rchild = new TreeNode(String.valueOf(Ran.getOperator()), null, null); 24 opeList.get(j + num1).setChild(lchild, rchild); 25 opeList.add(lchild); 26 opeList.add(rchild); 27 } 28 } 29 30 for(int i = 0; i < place.length; i++){ 31 if(place[i]){ 32 lnode = new TreeNode(String.valueOf(Ran.getNumber(Arithmetic.getLine())), null, null); 33 rnode = new TreeNode(String.valueOf(Ran.getNumber(Arithmetic.getLine())), null, null); 34 if(i%2 == 0){ 35 lchild = new TreeNode(String.valueOf(Ran.getOperator()), lnode, rnode); 36 opeList.add(lchild); 37 opeList.get(num1).setLchild(lchild); 38 } 39 else{ 40 rchild = new TreeNode(String.valueOf(Ran.getOperator()), lnode, rnode); 41 opeList.add(rchild); 42 opeList.get(num1).setRchild(rchild); 43 } 44 } 45 else{ 46 if(i%2 == 0){ 47 lchild = new TreeNode(String.valueOf(Ran.getNumber(Arithmetic.getLine())), null, null); 48 opeList.get(num1).setLchild(lchild); 49 } 50 else{ 51 rchild = new TreeNode(String.valueOf(Ran.getNumber(Arithmetic.getLine())), null, null); 52 opeList.get(num1).setRchild(rchild); 53 } 54 } 55 num1 = num1 + i%2; 56 } 57 } 58 }
括号添加及去掉:
1 /** 2 * 先对每个运算式添加括号,然后根据去括号法则,去掉多余的子式的括号 3 * 4 * @return string 5 */ 6 public String toString(){ 7 String Lstr = "", Rstr = "", Str = ""; 8 if(hasChild()){ 9 if(getRchild().hasChild()){ 10 if(str.equals("÷")){ 11 Rstr = getRchild().toString(); 12 } 13 else if(str.equals("×") || str.equals("-")){ 14 if(getRchild().str.equals("+") || getRchild().str.equals("-")){ 15 Rstr = getRchild().toString(); 16 } 17 else{ 18 Rstr = getRchild().toString().substring(1, getRchild().toString().length()-1); 19 } 20 } 21 else{ 22 Rstr = getRchild().toString().substring(1, getRchild().toString().length()-1); 23 } 24 } 25 else{ 26 Rstr = getRchild().str; 27 } 28 //左子树的情况同右子树类似 29 if(getLchild().hasChild()){ 30 if(str.equals("×") || str.equals("÷")){ 31 if(getLchild().str.equals("+") || getLchild().str.equals("-")){ 32 Lstr = getLchild().toString(); 33 } 34 else{ 35 Lstr = getLchild().toString().substring(1, getLchild().toString().length()-1); 36 } 37 } 38 else{ 39 Lstr = getLchild().toString().substring(1, getLchild().toString().length()-1); 40 } 41 } 42 else{ 43 Lstr = getLchild().str; 44 } 45 Str = "(" + Lstr + str + Rstr + ")"; 46 } 47 else{ 48 Str = str; 49 } 50 return Str; 51 }
结果计算:
1 /** 2 * 获取每个节点的运算结果,并检验除法 3 * 4 * @return result 5 */ 6 public String getResult(){ 7 if(hasChild()){ 8 switch(str){ 9 case "+": 10 return String.valueOf(Integer.parseInt(getLchild().getResult()) + Integer.parseInt(getRchild().getResult())); 11 case "-": 12 if(Integer.parseInt(getLchild().getResult()) - Integer.parseInt(getRchild().getResult()) < 0) { 13 setChild(getRchild(), getLchild()); //如果减法运算结果为负数,则只需要将左右孩子交换一下就行了 14 } 15 return String.valueOf(Integer.parseInt(getLchild().getResult()) - Integer.parseInt(getRchild().getResult())); 16 case "×": 17 return String.valueOf(Integer.parseInt(getLchild().getResult()) * Integer.parseInt(getRchild().getResult())); 18 case "÷": 19 if(getRchild().getResult().equals("0")){ //除数是0的情况 20 while(str.equals("÷")){ 21 str = String.valueOf(Ran.getOperator()); //重新生成运算符 22 } 23 return this.getResult(); 24 } 25 else if(Integer.parseInt(getLchild().getResult()) % Integer.parseInt(getRchild().getResult()) != 0){ 26 while(str.equals("÷")){ 27 str = String.valueOf(Ran.getOperator()); //重新生成运算符 28 } 29 return this.getResult(); 30 } 31 else 32 return String.valueOf(Integer.parseInt(getLchild().getResult()) / Integer.parseInt(getRchild().getResult())); 33 } 34 } 35 return str; 36 }
效果截图:
总结:在数据结构这一块还是存在很大问题,对算法和结构的理解欠缺,虽然在javaweb上面学会了许多东西,但是之前学的一些基础的东西还得多翻阅翻阅。
PSP0级过程文档