2019面向对象程序设计第一单元总结

<font size=6>2019面向对象程序设计第一单元总结</font>java

<font size=5>一.三次做业的设计思路</font>

<font size=4>Ⅰ.仅含常数和幂函数的多项式求导</font>

<font color="red" face="楷体" size="4">(1)思路一:WF判断与分项结合,避免大正则爆栈问题</font>正则表达式

​ 第一次做业中,多项式的结构具备极强的规律性,因此很多同窗想到用正则表达式匹配整串,但忽略了大正则存在回溯次数过多可能会致使爆栈。所以正确的处理策略之一是,单独处理输入中的空格,正负号以及非法字符,而后用正则匹配表达式中的每一项,获得的全部项相加,若与原表达式不相同,则判为“WRONG FORMAT!”,不然,则输出求导结果。express

正则匹配处理空格与符号后的每一项:架构

Pattern pattern = Pattern.compile("([-+]+(([-+]?(\\d+\\*)?x(\\^[-+]?\\d+)?)|([-+]?\\d+)))");

而后用<font color="blue">Matcher</font>中的<font color="blue">find()</font>函数实现分离每一项,用<font color="blue">Matcher</font>中的<font color="blue">group()</font>函数实现项处理。函数

<font color="red" face="楷体" size="4">(2)思路二:用ArrayList、LinkedList或HashMap实现动态插入新项</font>测试

​ 笔者在第一次做业中采用的是利用泛型的LinkedList实现优化

public class PolyHandler {
    //利用链表构造求导后的新多项式
    private LinkedList<String[]> polynomial;
    
    //构造函数
    PolyHandler(LinkedList<String[]> polynomial) {
        this.polynomial = polynomial;
    }

重点:在动态添加元素的过程当中,实现同类项的合并,可以大大减小优化复杂度。this

​ 笔者利用PolyHandler类中的merge函数实现求导后多项式合并新项spa

void merge(String[] item)

下图为第一次做业个人类图设计

StringMatcher用于初步判断输入是否合法

ItemHandler为项处理类

PolyHandler为多项式处理类

MainHandler为主类

<font size=4>Ⅱ.仅含常数、幂函数和三角函数的多项式求导</font>

<font color="red" face="楷体" size="4">(1)思路一:本次做业仍可利用正则进行分项</font>

​ 笔者认为,第二次做业相比第一次多项式求导做业而言,在处理非法输入与求导方面对总体架构的改变不大,所以笔者沿用了第一次做业的设计,复用了较多的类。

​ 正则分项:

Pattern pattern = Pattern.compile("[-+](\\d+|(x(\\^[-+]?\\d+)?)|" +
                "(sin\\(x\\)(\\^[-+]?\\d+)?)|(cos\\(x\\)(\\^[-+]?\\d+)?))" +
                "(\\*[-+]?(\\d+|(x(\\^[-+]?\\d+)?)" +
                "|(sin\\(x\\)(\\^[-+]?\\d+)?)|(cos\\(x\\)(\\^[-+]?\\d+)?)))*");

emmm......看上去是否是很复杂呢,在第二次做业咱们已经能够上递归降低分析了!

<font color="red" face="楷体" size="4">(2)思路二:用HashMap处理多个Key,化简时有巨大优点</font>

​ 自定义一个类,包含多个Key,将这个类做为HashMap的Key类型,并实现这个类的哈希函数和相等性断定函数。

1.哈希函数

int hashcode()

2.相等性断定函数

boolean equals(object obj)

下图是笔者本身设计的HashKey类中重写的核心方法

注:在第二次做业中,利用HashMap实现同类项的合并相比ArrayList与LinkedList有更大优点。

下图为我第二次做业的类图

​ StringMatcher类用于判断输入是否合法

​ HashKey类为本身设计构造的HashMap的Key类型

​ Expression类为表达式处理类

​ Item类为项处理类

​ Derivation类为求导类

<font size=4>III.包含常数、项、幂函数与嵌套三角幂函数多项式的求导</font>

<font color="red" face="楷体" size="4">核心思想——递归降低分析法:表达式由项构成,项由因子构成,因子的种类能够是表达式,幂函数,常数项,三角函数类。</font>

1.表达式:读取项,用LinkedList存储项:

LinkedList<Term> parseExpression()

2.项:读取因子,用LinkedList存储因子:

Term parseTerm()

3.因子

//外包函数,分析因子种类,而后分种类爬取因子
Factor parseFactor()
//获取常数项因子
Factor getConstantFactor()
//获取幂函数因子
Factor getXFactor()
//获取正弦函数因子
Factor getSinxFactor()
//获取余弦函数因子
Factor getCosxFactor()
//获取表达式因子
Factor getExpressionFactor()

为使逻辑清晰,可把因子种类定义为枚举类型。

public enum FactorType {
    constant,x,sin,cos,expression
}

下图为第三次做业个人类图

​ StringMatcher类用于判断输入格式是否为正确格式

​ Expression类为表达式处理类

​ Term类为项处理类

​ Factor类为因子处理类

​ FactorType枚举类型定义了因子类型

<font size=5>二.优化策略简介</font>


笔者会在另外一篇博文中对优化策略进行详解,在此仅说下总体思路。</u>

题外话,笔者在三次做业的优化中均取得了还不错的成绩,第一次做业满分,第二次做业第11名,第三次做业前10名

<font color ="lightgreen">1).第一次做业优化要点:</font>

①合并同类项

②正项前移

<font color ="lightgreen">2).第二次做业优化要点:</font>

①合并同类项

②利用三角函数公式简化(主要采用了如下四类公式):

1°  sin(x)^2 + cos(x)^2 = 1

​			2° 1-sin(x)^2 = cos(x)^2

​			3° 1-cos(x)^2 = sin(x)^2

​			4° sin(x)^4 - cos(x)^4 = sin(x)^2 - cos(x)^2

③正项前移

<font color="lightgreen">3).第三次做业优化要点:</font>

​ 笔者认为,第三次做业的优化重点不在于利用三角函数公式简化,而在于在可控时间复杂度下利用递归降低实现同类项的合并,这便须要重写Expression类、Term类、Factor类的hashcode()和equals()函数

<font size=5>三.综合三次做业的方法复杂度的分析</font>


第一次做业:

第二次做业:

第三次做业:

​ 能够看出,随着三次做业的层层递进,工程的方法数目与方法复杂度均在上升。因为2、三次做业的优化相对复杂,故我在相应的类中实现了较多复杂度较高的方法来进行相应的优化,具体方法逻辑可参考类图。

<font size=5>四.Bug分析</font>


​ 三次做业个人强测所有经过,均没有出现bug,加上优化分,笔者在三次做业中的强测得分分别为100分、99.2839分、96.7647分。

​ 但在第三次做业中,我被别的玩家hack了一个点,系我在化简过程当中一个if语句判断失误,去除了三角函数中表达式因子的括号,致使输出格式有问题。这也告诫我,在优化过程当中,必定要考虑全面。

<font size=5>五.高效Debug和Hack策略分析</font>


笔者认为,其实要想成为OO互测的顶级玩家,必需要拥有一台本身编写的评测机,千万不要偷懒。

<font color="red" face="楷体" size="4">(1)构建本身的“强测”评测机(全面覆盖):</font>

① 自动生成随机表达式串

② 让本组成员的程序互拍,寻找不一样结果。

③ 判断错误结果的来源、错误结果的种类(即Wrong Format Error、Wrong Value Error仍是Wrong Derivative Error),并输出到指定文件

​ 下图是用Python实现的第三次做业的评测机。

<font color="red" face="楷体" size="4">(1)精心构造测试样例(重点针对):</font>

​ 评测机生成的数据太随机,所以每每有些bug会疏漏掉,须要本身读懂评测屋内的代码,并分析其架构和逻辑上的失误,并构造相应样例。

​ 好比第二次做业的一个针对优化的典型hack样例:

x*sin(x)^4*cos(x)^-4+x*sin(x)^5*cos(x)^-5+x*sin(x)^2*cos(x)^-2+x*cos(x)^-3+x*sin(x)^6*cos(x)^-6

​ 第三次做业的一个典型hack样例

cos((((-+((((sin(x)))))))))

<font size=5>六.Applying Creational Pattern</font>


​ 工厂模式与抽象工厂

​ 对于本次做业可使用工厂模式来建立表达式,项,因子,咱们只需定义一个建立对象的接口,让实现了该接口的子类本身决定实例化哪个工厂类。在咱们明确地计划不一样条件下建立不一样实例时,工厂模式将十分管用。

​ 抽象工厂模式是围绕一个超级工厂建立其余工厂。在抽象工厂模式中,接口是负责建立一个相关对象的工厂,不须要显式指定它们的类。每一个生成的工厂都能按照工厂模式提供对象,这样咱们就不用花费时间在选择接口上了。

<font size=5>七.总结与展望</font>


​ 北航的OO课正在不断变好,感谢老师、助教和为其余为这门课默默付出的人。我会再接再砺,不断提高本身的分析能力和代码能力。

相关文章
相关标签/搜索