https://git.coding.net/verde/YF_HomeWork.git
1.需求分析:
1. 使用JAVA编程语言。
2. 接收一个输入参数n,随机产生n道四则运算练习题,符号用+-*÷来表示。
3. 每个数字在 0 和 100 之间。
4. 运算符在3个到5个之间并且每道练习题至少要包含2种运算符。
5. 运算过程中不得出现负数与非整数。
6. 将学号和生成的练习题及对应答案输出到文件“result.txt”中,不输出额外信息。
7. 支持命令行测试
2.基本功能:
- 实现加减乘除四则运算
- 输入整数n的判断,随机数的生成
- 除数为零时以及除得结果不是整数时题目的变化
- 命令行输入,java文件相关的应用,输出结果到result.txt
3.扩展功能
- 括号的生成、实现以及运算
- 重复括号时自动减括号,例如:((3+4+5*67))÷2这种情况需要删除一对括号
4.设计实现
设计包括你会有哪些类,这些类分别负责什么功能,他们之间的关系怎样?你会设计哪些重要的函数,关键的函数是否需要画出流程图?函数之间的逻辑关系如何?
如图主要有四个类:
5.算法详解
要求:请描述你生成题目与解答题目用到的算法,并说明在求解题目时你是如何使用调度场算法或其他算法来处理不同运算符的优先级的?
具体参考:
http://www.cnblogs.com/edisonchou/p/4649954.html
数据结构基础温故-4.树与二叉树(下)
https://www.jellythink.com/archives/688
从后缀表达式建立表达式树
由于从中序表达式(也就是正常的表达式)转换成树结构式在括号的处理上有点麻烦。所以将表达式转换为后序表达式再转成树结构,就可以不去处理括号。
表达式生成
根据运算符个数循环生成表达式:
每次生成一个基础数符对:`Num`+`Operator`
根据随机数判断是否生成括号与括号的位置
1.没有括号:`原表达式`+`Num`+`Operator`
2.括号在当前表达式后面:`原表达式`+`(`+`Num`+`Operator`,括号计数器加1
3.括号在表达式前面:`(`+`原表达式`+`Num`+`Operator`,括号计数器加1
判断当前表达式是否存在为配对的括号
若括号计数器不为零
1.需要加:`原表达式`+`Num`+`)`+`Operator`,括号计数器减1
2.不加:`原表达式`+`Num`+`Operator`
循环结束时判断括号对是否匹配完全
若括号计数器不为零
循环在表达式末尾加上`)`;
由于基础数符对为`Num`+`Operator`的形式,在循环结束时需要去掉末尾多余的一个Operator
判断是否存在包裹整个表达式的括号,即括号对内长度是否等于表达式长度(不算括号),若存在则去除表达式两端的括号,再次判断。
二叉树生成
具体生成方式参考上面的程序设计基础,我在树的类中加上的代表运算结果的值`value`,用来存放当前树的运算结果。
当生成节点的对象为一个`Num`的时候,节点的值就位`Num`本身。
当对象为一个`Operator`的时候,节点的值为左右子树进行当前运算符运算后的结果,即`value Op value`
当表达式扫描完成,计算过程也就结束了,最后根节点的值就是表达式的运算结果。
查重方式
由于采用了二叉树的结构存放表达式,所以可以再二叉树生成的时候将树根据一点规则判断左右子树的对象
若生成节点的对象是`*`或者`+`
1.左右子树的值不同,则值大的作为左子树
2.左右子树的值相同时,判断子树的运算符优先级大小,优先级大的作为左子树
3.运算符优先级相同,判断子树下的左子树值得大小,值大的作为左子树
4.若为子树为一个为数字,一个为运算符,则运算符作为左子树
5.若左右子树都为数字,则值大的作为左子树
根据这个规则,基本上包含了交换律可能出现的情况,将可以有交换律变换得到的表达式都转为一个统一的表达式,在根据检查已生成的表达式树的结构,若存在重复的就放弃当前表达式,重新生成并查重。
在这个规则下
3+2+1 与 3+1+2 两个表达式不是重复的表达式
因为不能再有限次的交换律加成为相同的表达式。
这个具体说明在原版的题目中
6.测试运行
ps:你的程序必须是可运行的,请展示程序的运行截图,包括题目要求实现功能对应的运行截图。这些截图说明你的程序确实完成了项目需求,如果程序实现了扩展需求,也请大方秀出来。
运行结果:
生成result.txt文件:
命令行输入:运行结果
7.比较满意的代码片段
1 //生成二叉树
2 public void buildBTree() {
3 GetResultDemo lchild, rchild, lnode, rnode;
4
5 if (num == 1) {
6 lchild = new GetResultDemo(String.valueOf(ToolDemo.getNumber(10)), null, null);
7 rchild = new GetResultDemo(String.valueOf(ToolDemo.getNumber(10)), null, null);
8 root = new GetResultDemo(String.valueOf(ToolDemo.getSign()), lchild, rchild);
9 } else {
10 int num1 = 0;
11 int n = getDeep() - 3;
12 boolean[] place = ToolDemo.getChildPlace(num);
13 root = new GetResultDemo(String.valueOf(ToolDemo.getSign()), null, null);
14 opeList.add(root);
15
16 for (int i = 0; i < n; i++) {
17 for (int j = 0; j < (int) Math.pow(2, i); j++, num1++) {
18 lchild = new GetResultDemo(String.valueOf(ToolDemo.getSign()), null, null);
19 rchild = new GetResultDemo(String.valueOf(ToolDemo.getSign()), null, null);
20 opeList.get(j + num1).setChild(lchild, rchild);
21 opeList.add(lchild);
22 opeList.add(rchild);
23 }
24 }
总结1:你设计的程序如何实现软件设计的'模块化'原则。
模块化有助于信息隐蔽和抽象,有助于表示复杂的系统。编写程序时经常会出现越
敲越乱的现象,并且有时候自己都会忘记自己的代码结构,这是让人很头疼的一件事情。
为此我的办法主要是并建立工具类,对于每个小的功能直接在工具类中编写相应的方法,
避免代码的重复缀余。编写时尽量面向对象,面向过程常常会把问题复杂化。编写类时一
个重要的原则是“低耦合,高内聚”,每个类的职责要清晰,同时尽量降低类与类之间的联系。
此次项目编写其实也有很多疏忽的地方,一开始建立类并不明确,也有很多重复代码,
后来查阅了很多资料屡次修改简化,不得不说这次作业让我对于项目编写又多积累了
一些经验,也了解到了算法的重要性。
展示PSP,这个环节重要的是让自己看到自己的估计和实际消耗时间,哪个环节耗时最多,哪个环节估计和实践相差巨大?为什么?
PSP2.1 |
任务内容 |
计划共完成需要的时间(min) |
实际完成需要的时间(min) |
Planning |
计划 |
8 |
6 |
· Estimate |
· 估计这个任务需要多少时间,并规划大致工作步骤 |
10 |
20 |
Development |
开发 |
1300 |
1600 |
· Analysis |
· 需求分析 (包括学习新技术) |
180 |
260 |
· Design Spec |
· 生成设计文档 |
5 |
6 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
4 |
6 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
3 |
3 |
· Design |
· 具体设计 |
10 |
12 |
· Coding |
· 具体编码 |
36 |
21 |
· Code Review |
· 代码复审 |
7 |
9 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
24 |
30 |
Reporting |
报告 |
90 |
60 |
· Test Report |
· 测试报告 |
20 |
15 |
· Size Measurement |
· 计算工作量 |
10 |
5 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
60 |
40 |
总结2:
这次的作业确实是自己花了几天时间一步一步认真设计敲出来的,虽然之前比较认真的学习过java,但也只限于实现一些简单的toy program,直到这次才是真正的用java做出了一个项目,为了完成作业在工作室每天晚上坐到九点回寝室洗漱接着做项目到十一点多,满脑子都是代码…还好完成了这个作业,包括作业的附加部分,还是很有成就感的。
耗时最多的地方当然在于算法,之前大一没有好好学习算法,大二选择了后端也忽视了算法的重要性,导致在开发过程中查阅了大量资料。这次作业使我对自己有了一个更加清晰的认识,也很感谢自己在做不出来的时候没有放弃,而是一直坚持到最后。今后一定会更加重视算法并在平时生活中多加练习。