第二次博客作业

                                      BLOG2

前言:这次题目集难度评价:难度都比较大,均耗费大量时间完成,但仍然有两次没有拿到满分,只有题目集5拿到了满分,期中考试的难度一般,看懂题目后完成程序的变成就没太大的难度。题目集4有三道题,但仅仅只拿到了一道满分,题目中涉及了许多数学中线段与三角形的交点与面积问题,每题里都有个别选项的分没拿到以及格式错误和点错误的分没拿到。题目集6的第二题,难度较题目4又有所上升,尤其里面的选项4情况太多,导致没完成其功能,到最后分数只有71分。

总体来说这三道习题集总体而言难度较大,虽然后面两次的习题集的题量并没有很多,但也使用大量时间完成。

三次作业大概知识点为正则表达式的使用,对数据的储(容器基础类的封装和继承)字符串内的字符排序字符串处理,基本数组排序,以及split()函数:拆分字符串。通过指定分隔符对字符串进行切片,并返回分割后的字符串列表

课堂作业所留下的链表训练,一开始的编写毫无思路,但理清链表的原理后显得较为简单。

 

设计与分析:

图形类设计的题目:

常情况输出:如果不符合基本格式,输出"Wrong Format"。如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"

题目集4里面对于三角形的输入格式的判断比较简单,偏向与c语言的思路,单纯对自己所能想到的错误格式进行编写,例如:         

  for(int i = 2;i<str.length();i++) {

               if((str.charAt(i)=='+'||str.charAt(i)=='-')&&(str.charAt(i+1)=='+'||str.charAt(i+1)=='-')) {

               sum++;

               }

               if(str.charAt(i)==','||str.charAt(i)==' ') {

               if(i+2<=str.length()-1) {

               if(str.charAt(i+1)=='0'&&str.charAt(i+2)>='0'&&str.charAt(i+2)<='9') {

                   sum++;

                   }

               }                

               a[j] = str.substring(k,i);        

               k = i+1;

               j++;

               }

              

               if(i==str.length()-1) {

               a[j] = str.substring(k);

               }

               if(str.charAt(i)=='.') {

               if(i==2) {

               sum++;

               }

               else if(i==str.length()-1) {

               sum++;

               }

               else {

               if(str.charAt(i-1)==' '||str.charAt(i+1)==' ')

               sum++;

               }

               }

              }

              for(int b = 2;b<str.length();b++) {

               if(str.charAt(b)==' ') {

               n++;

               }

               }

              if(sum!=0) {

               System.out .println("Wrong Format");

              }

              else if(j>5) {

               System.out .println("Wrong Format");

              }

              else if(n!=2) {

               System.out .println("Wrong Format");

              }

但这样判断导致对许多格式错误以及点错误有许多地方无法判断出来,后续学习了正则表达式,确实方便了许多且大部分的非法情况都能排查出来,使用在题目集6中使用,使得程序更加的简单,代码如下:

if(str.matches("[1-5]:((\\+|\\-)?(\\d+)(\\.)?(\\d+)?,(\\+|\\-)?(\\d+)(\\.)?(\\d+)?\\s)*"+"((\\+|\\-)?(\\d+)(\\.)?(\\d+)?\\,(\\+|\\-)?(\\d+)(\\.)?(\\d+)?)" + "\\s?")) 

若不符合上述正则表达式的形式,则输出Wrong Format.

 

 

题目里线与点的交点个数较为复杂,对其的解决方法我进行一次一次的枚举将其各种情况写出。首先运用计算4中的方法判断两直线是否平行,再计算两直线相交的交点坐标,再通过坐标值大小来判断交点是否位于线段内。枚举法如下:

if(a1==1&&a2==1&a3==1) {

if(x6==x7&&y6==y7) {

Three onearea1 = new Three(x3,y3,x4,y4,x8,y8);

Three onearea2 = new Three(x4,y4,x5,y5,x8,y8);

System.out.println("2 "+new DecimalFormat("0.0#####").format(Math.min(onearea1.area1(),onearea2.area1()))+" "+new DecimalFormat("0.0#####").format(Math.max(onearea2.area1(),onearea1.area1())));

}

 

以此对每条交点进行计算。

在保留小数点的时候使用了

DecimalFormat format = new DecimalFormat("0.0#####");

new DecimalFormat("0.0#####").format(Math.min(onearea1.area1(),onearea2.area1()))

行只保留小数点后6位,多余部分采用四舍五入规则进到最低位。

 

在计算三角形面积时使用海伦公式:

 double a = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));

 double b = Math.sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));

 double c = Math.sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3));

 double p=(a+b+c)/2;

 double S=Math.sqrt(p*(p-a)*(p-b)*(p-c));

在计算面积保留两位小数时使用以下方法避免误差:

whole = Math.abs((x2 * y3 + x3 * y4 +x4 * y2 - x3 * y2 - x4 * y3 - x2 * y4) / 2.0D);

按面积大小依次输出三角形被直线分割成两部分的面积时则采用Math.maxMax.min函数进行输出

System.out.println("2 "+new DecimalFormat("0.0#####").format(Math.min(onearea1.area1(),onearea2.area1()))+" "+new DecimalFormat("0.0#####").format(Math.max(onearea2.area1(),onearea1.area1())));

}

 

题目集6里面的四边形因题目的选项大部分有一定的关系,所以大致的想法与题目集4里面的三角形求法差不多。

题目集4图形设计思路:先输入一串字符串,运用正则表达式将数据分割为几分,再根据题目所给的选项进行编译

题目集6图形设计思路:先输入一串字符串,运用正则表达式将数据分割为几分,后连选项还需判断组成为三角形还是四边形

选项1:将输入的数据进行格式转换成浮点数类型,再运用数学知识求出坐标之间的距离,再根据距离判断是否可以组成三角形,如果为三角形,在进行是否为等边或等腰三角形。double a = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));

 double b = Math.sqrt((x3-x2)*(x3-x2)+(y3-y2)*(y3-y2));

 double c = Math.sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3));

 if(a+b>c&&a+c>b&&b+c>a) {

 if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)<(x1-x3)*(x1-x3)+(y1-y3)*(y1-y3)||(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(x1-x3)*(x1-x3)+(y1-y3)*(y1-y3)<(x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)||(x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)+(x1-x3)*(x1-x3)+(y1-y3)*(y1-y3)<(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) {

 System.out.print("true false false");

 }else if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)==(x1-x3)*(x1-x3)+(y1-y3)*(y1-y3)||(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(x1-x3)*(x1-x3)+(y1-y3)*(y1-y3)==(x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)||(x3-x2)*(x3-x2)+(y3-y2)*(y3-y2)+(x1-x3)*(x1-x3)+(y1-y3)*(y1-y3)==(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) {

 System.out.print("false true false");

 }

 else {

 System.out.print("false false true");

 }

 }

 else {

 System.out.print("date error");

 }

输入四个点坐标,计算输出前两个点所构成的直线与后两点构成的直线的交点坐标:首先采取公式算出万能的交点公式

 x0 = (((x1-x2)*y1-(y1-y2)*x1)*(x3-x4)-((x3-x4)*y3-(y3-y4)*x3)*(x1-x2))/((y2-y1)*(x3-x4)-(y4-y3)*(x1-x2));

         y0 = (((x3-x4)*y3-(y3-y4)*x3)*(y2-y1)-((x1-x2)*y1-(y1-y2)*x1)*(y4-y3))/((y2-y1)*(x3-x4)-(y4-y3)*(x1-x2));

然后求交点x0与另外四点的x进行比较得出结果。

输入三个点坐标,输出第一个点与另外两点连线的垂直距离。运用的是向量关系去求,避免了斜率不存在的情况。

if((x1==x2&&y1==y2)||(x1==x3&&y1==y3)||(x3==x2&&y3==y2)) {

System.out.println("points coincide");

}

else if(x1==x2&&x1==x3) {

 System.out.println("true");

}

else {

if((y1-y2)/(x1-x2)==(y3-y2)/(x3-x2))

 System.out.println("true");

else

 System.out.println("false");

}

三道有关图形类设计的题目的类图如下:大部分是根据点的个数创建类。

 

 

 

 

 

 

 

 

 

 

输出第一个是否在后四个点所构成的四边形(限定为凸四边形,不考虑凹四边形)或三角形(判定方法见选项4)的内部使用了面积法,面积相等则在四边形内,若其中两点与第一个点围成面积为0时,则在四边形上,代码如下:

Four area = new Four(x2, y2, x3, y3, x4, y4, x5, y5);

Three area1 = new Three(x1, y1, x2, y2, x3, y3);

Three area2 = new Three(x1, y1, x3, y3, x4, y4);

Three area3 = new Three(x1, y1, x4, y4, x5, y5);

Three area4 = new Three(x1, y1, x2, y2, x5, y5);

double whole = area.area1();

double whole1 = area1.area1();

double whole2 = area2.area1();

double whole3 = area3.area1();

double whole4 = area4.area1();

if(whole==0) {

System.out.println("not a quadrilateral or triangle");

return;

}

else {

if(whole==whole1+whole2+whole3+whole4) {

if(whole1==0||whole2==0||whole3==0||whole4==0) {

System.out.println("on the quadrilateral");

return;

}

else {

System.out.println("in the quadrilateral");

return;

}

}

else {

System.out.println("outof the quadrilateral");

return;

}

}

ATM的设计则使用容器进行储存,进行多个类之间的储存

ArrayList<String> ATMList1 = new ArrayList<>();

ATMList1.add("01");

ATMList1.add("02");

ATMList1.add("03");

ATMList1.add("04");

Bank CCB = new Bank("中国建设银行", ATMList1);

容器的使用方便了内部内容的比对。银行里存储的信息,是用户包含了账户信息然后包含卡还是一张卡对应一个用户。

 

链表:

根据老师所发的代码进行函数内部功能的编写,链表中的增删查几个选项,先要了解其如何改变。后续的双向链表的修改与单向相比多了previous,只需在多加考虑前一节点关系即可。

创建一个节点类,其中节点类包含两个部分,第一个是数据,第二个是引用域

在增加的过程中,将加入的next为加入所在位置的next,例如:

Node<E> curr = new Node<>();

curr.setData(theElement);

curr.setNext(null);

if (this.size == 0) {

head.setNext(curr);

tail = curr;

} else if (index == this.size + 1) {

this.tail.setNext(curr);

tail = curr;

} else {

Node<E> tempNode = head;

for (int i = 1; i < index; i++) {

tempNode = tempNode.getNext();

}

curr.setNext(tempNode.getNext());

curr.setPrevious(tempNode);

tempNode.setNext(curr);

tempNode.getNext().setPrevious(curr);

}

删减过程大致为链表为空1:不用删除2、链表不为空:先循环找要删除的节点将删除节点的前一个节点的next为删除节点的next.,代码如下:

if(index<1||index>size) {

return;

}

else {

curr = head;

for(int i=1;i<index;i++) {

curr=curr.getNext();

}

curr.setNext(curr.getNext().getNext());

curr.getNext().setPrevious(curr);

}

输出则利用循环一步一步输出链表内部的数据。代码如下:

curr = head.getNext();

while(curr!=null) {

System.out.print(curr.getData()+" ");

curr = curr.getNext();

 

 

 

 

此题考验的是根据类图编写代码,根据题目要求来具体编写,总体过程较简单;

后两题是在每一题的前提下进行迭代,第二题创建一个父类Element,第三题则使用容器;

abstract class Element{

public void display() {

 

}

}

ArrayList<Element> list = new ArrayList<>();

第三题中的对该容器进行相应增、删、遍历操作,使用的是自有函数。

public void add(Element element) {

list.add(element);

}

 

public void remove(int index) {

if(index<1||index>list.size())

return ;

else

list.remove(index-1);

 

}

以上为这几道题的设计分析。

 

 

踩坑心得:

在运用正则表达式的时候忘记在,前加\\导致错误输入未全部检查出来。

在保留小数点方面一开始使用printf(%.f,x)进行输出,虽能满足小数点控制,但无法进行四舍五入的操作,后进行查找,发现了DecimaFormat()方法的运用,这问题才得以解决。

New

DecimalFormat("0.0#####").format(Math.max(onearea2.area1(),onearea1.area1())));

3.使用String[] a = str.split("\\D+");时没考虑到第一个元素可能为“”,导致开始就得到两分。修改代码:for (int i = 0; i < a.length; i++) {

if (a[i].matches("\\d+")) {

b = Integer.parseInt(a[i]);

sum = sum + b;

}

}

4.链表一开始未对head进行赋值,使运行时代码一直报head为空的情况。

public DoubleLinkedList() {

super();

// TODO Auto-generated constructor stub

head = new Node<E>();

head.setNext(null);

curr = tail = null;

this.size = 0;

}

 

改进建议:

1.要善于用Java中一些功能方便的类,这样可以大大的提高我们的解题效率。

2.在写题目前可以列举一个小菜单,方便后续程序的编写,以及能更加清楚创建3.的各个类之间的关系,以及这个类有怎样的功能

4.在进行代码的编写时应尽量避免代码的重复编写,使代码更加简洁.

5.编写代码时应逻辑缜密,这样相关代码便能拿出来直接使用。

6.老师讲课讲到重要的知识时,希望老师讲的尽量详细一些。

 

总结:

1.通过这几次的题目集以及链表的练习,我了解了如何快速的、有效的、正确的编写程序,虽然做作业时花费了大量的时间在图形类设计的题目和链表上但是通过这几类题使得我的编程能力大大的加强了。

2.通过次作业的练习,强化了我对java语言的使用和理解

3.积累了一些debug的经验,深刻认识到了调试的重要性,学会了调试的基本技巧,如何设置断点,单步进入,跟踪参数,以及更改代码的逻辑顺序,排除逻辑错误,对提高代码的质量大有改善。

4.在学习Java的过程中,我们不要受限于C语言的逻辑思维了,我们要好好利用Java的优点

5.老师在课堂中讲的都是如何去编写代码,这样在帮助我们形成一种良好的写Java的思维,对我的编写非常有用。

6.正则表达式在之前是从未接触过的内容,所以必须自学,在理解了正则表达式的运作原理和作用后,可以将表达式的每一个项单独拆分出来,非常方便。

posted @ 2022-05-01 20:28  清风霁雨  阅读(60)  评论(0)    收藏  举报