JAVA学习--第二次作业总结
目录
前言
这几周的时间里简单了解了java三大特性:1、封装,是指隐藏对象的属性和实现细节,仅对外提供公共访问方式;2、继承,从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力;3、多态,一个方法可以有多种实现版本,即“一种定义, 多种实现”。下面从这几次的练习来说一说我对这些特性的理解。
题目集04:
- 主要考察对于字符串的处理,类的设计以及数学能力
- 题目量不大,但是难度较高,主要是测试点通过不易
双向链表练习:
- 主要考察c语言链表基础以及java的简单语法
- 难度不高,通过画图逻辑较清晰,主要是边界值的考虑需注意
21级软件工程专业期中考试(OOP):
- 主要考察根据类图实现功能的能力以及java的简单语法掌握程度
- 题量不大,难度较易
设计与分析
题目集04:
-
7-1 点线形系列1-计算两点之间的距离
输入连个点的坐标,计算两点之间的距离
输入格式:
4个double类型的实数,两个点的x,y坐标,依次是x1、y1、x2、y2,两个点的坐标之间以空格分隔,每个点的x,y坐标以英文“,”分隔。例如:0,0 1,1或0.1,-0.3 +3.5,15.6。
若输入格式非法,输出"Wrong Format"。
若输入格式合法但坐标点的数量超过两个,输出“wrong number of points”。
输出格式:
计算所得的两点之间的距离。例如:1.4142135623730951
输入样例:
整数输入。例如:
0,0 1,1
输出样例:
在这里给出相应的输出。例如:
1.4142135623730951
输入样例1:
带符号double类型实数输入。例如:
+2,-2.3 0.9,-3.2
输出样例1:
在这里给出相应的输出。例如:
1.42126704035519
输入样例2:
格式非法。例如:
++2,-2.3 0.9,-3.2
输出样例2:
在这里给出相应的输出。例如:
Wrong Format
输入样例3:
点的数量超过两个。例如:
+2,-2.3 0.9,-3.2 +2,-2.3
输出样例3:
在这里给出相应的输出。例如:
wrong number of points
code
import java.util.Scanner; public class Main { public static void main(String[] args){ Scanner input = new Scanner(System.in); int count = 0,count1 = 0,count2 = 0; Point point1 = new Point(); String enter = input.nextLine(); if(enter.charAt(enter.length()-1)=='+'||enter.charAt(enter.length()-1)=='-'||enter.charAt(enter.length()-1)=='.'||enter.charAt(enter.length()-1)==','){ System.out.println("Wrong Format"); System.exit(0); } if(enter.indexOf(' ') == -1) { System.out.println("Wrong Format"); System.exit(0); }//没有用空格隔开 case8 if(enter.indexOf(',') == -1) { System.out.println("Wrong Format"); System.exit(0); }//不存在逗号 for(int i=0;i<enter.length();i++) { if(enter.charAt(i)==' ') { count++; } if(enter.charAt(i)==','&&enter.charAt(i+1)==',') {//逗号连续 count1++; } if(enter.charAt(i)=='.'&&enter.charAt(i+1)==' ') {//逗号连续 count1++; } if(enter.charAt(i)==','&&enter.charAt(i+1)=='.') {//(2,.1)小数点前无数字 count1++; } if(enter.charAt(i)==',') {//如果只有一个逗号的情况(1+2) (2,2) count2++; } if(enter.charAt(i)=='+'&&enter.charAt(i+1)==',') {//(数字后面有正负号) count1++; } if(enter.charAt(i)=='-'&&enter.charAt(i+1)==',') {//(数字后面有正负号) count1++; } else if(enter.charAt(i)=='+'&&enter.charAt(i+1)==' ') {//(数字后面有正负号) count1++; } else if(enter.charAt(i)=='-'&&enter.charAt(i+1)==' ') {//(数字后面有正负号) count1++; } if(enter.charAt(i)=='.'&&enter.charAt(i+1)==',') {//小数点后面无数字 count1++; } if(enter.charAt(i)==','&&enter.charAt(i+1)==' ') {//一个坐标后面继续有, count1++; } else if(enter.charAt(i)=='0'&&enter.charAt(i+1)=='0') { count1++; } else if(enter.charAt(i)=='+'&&enter.charAt(i+1)=='+') { count1++; } else if(enter.charAt(i)=='-'&&enter.charAt(i+1)=='-'){ count1++; } else if(enter.charAt(i)=='+'&&enter.charAt(i+1)=='.') { count1++; } else if(enter.charAt(i)=='-'&&enter.charAt(i+1)=='+') { count1++; } else if(enter.charAt(i)=='+'&&enter.charAt(i+1)=='-') { count1++; } } if(count1>=1||count2==1) { System.out.println("Wrong Format"); System.exit(0); } if(count>=2) { System.out.println("wrong number of points"); } if(count1==0&&count==1){ String [] p1 = enter.split(" "); String []point1xy = p1[0].split(","); String []point2xy = p1[1].split(","); point1.setX(Double.parseDouble(point1xy[0])); point1.setY(Double.parseDouble(point1xy[1])); Point point2 = new Point(Double.parseDouble(point2xy[0]),Double.parseDouble(point2xy[1])); System.out.println(point1.Distance(point2)); } } } class Point{ private double x,y; public Point() { super(); // TODO 自动生成的构造函数存根 } public Point(double x, double y) { super(); this.x = x; this.y = y; } public double getX() { return x; } public void setX(double x) { this.x = x; } public double getY() { return y; } public void setY(double y) { this.y = y; } public double Distance(Point p) { double distance; distance=Math.sqrt((x-p.x)*(x-p.x)+(y-p.y)*(y-p.y)); return distance; } }
本题的难度在于字符串的处理,这里我采用的是利用循环两个一组的判断可能的错误情况,实际上这种方法并不明智,会出现一些情况考虑不到,也会误判一些正确的情况。所以正确的思路应该是利用正则表达式来判断输入字符串的合法性,在写这个题的时候并未了解到正则表达式,所以采取了一个碰巧的方式。这里我们可以简单介绍一下正则表达式:正则表达式定义了字符串的模式,可以用来搜索、编辑或处理文本,正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。合理使用正则表达式对于文本的处理效率会变高很多。在判断完字符串的合法性后,我采用了public String split(String regex ,int limit)
方法来将字符串转化为坐标的值从而来进行计算。regex
为正则表达式分隔符,limit
为分隔的份数。需要注意的是这个方法返回的是字符串数组,所以需要使用字符串数组来接收返回的值。
-
7-2 点线形系列2-线的计算
用户输入一组选项和数据,进行与直线有关的计算。选项包括:
1:输入两点坐标,计算斜率,若线条垂直于X轴,输出"Slope does not exist"。
2:输入三个点坐标,输出第一个点与另外两点连线的垂直距离。
3:输入三个点坐标,判断三个点是否在一条线上,输出true或者false。
4:输入四个点坐标,判断前两个点所构成的直线与后两点构成的直线是否平行,输出true或者false.
5:输入四个点坐标,计算输出前两个点所构成的直线与后两点构成的直线的交点坐标,x、y坐标之间以英文分隔",",并输出交叉点是否在两条线段之内(不含四个端点)的判断结果(true/false),判断结果与坐标之间以一个英文空格分隔。若两条线平行,没有交叉点,则输出"is parallel lines,have no intersection point"。
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。
例如:1:0,0 1,1
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
不论哪个选项,如果格式、点数量都符合要求,但构成任一条线的两个点坐标重合,输出"points coincide",
输出格式:
见题目描述。
输入样例1:
选项1,两点重合。例如:
1:-2,+5 -2,+5
输出样例:
在这里给出相应的输出。例如:
points coincide
输入样例2:
选项1,斜率无穷大的线。例如:
1:-2,3 -2,+5
输出样例:
在这里给出相应的输出。例如:
Slope does not exist
输入样例3:
选项1,斜率无穷大。例如:
1:-2,3 -2,+5
输出样例:
在这里给出相应的输出。例如:
Slope does not exist
输入样例4:
选项1,符合格式输入,带符号/不带符号数混合。例如:
1:-2.5,3 -2,+5.3
输出样例:
在这里给出相应的输出。例如:
4.6
输入样例5:
选项2,计算第一个点到另外两点连线的垂直距离。例如:
2:0,1 1,0 2,0
输出样例:
在这里给出相应的输出。例如:
1.0
输入样例6:
选项3,判断三个点是否在一条线上。例如:
3:0,1 2,2 5,3
输出样例:
在这里给出相应的输出。例如:
false
输入样例7:
选项4,判断两条线是否平行。例如:
4:0,1 0,2 2,1 3,0
输出样例:
在这里给出相应的输出。例如:
false
输入样例8:
选项5,判断两条线的交点。例如:
5:0,0 -1,-1 0,2 3,-1
输出样例:
在这里给出相应的输出,交点坐标之间以英文","分隔,判断结果与坐标之间以一个英文空格分隔。例如:
1.0,1.0 true
输入样例9:
选项5,判断两条线的交点。但两条线平行例如:
5:0,0 -1,-1 2,3 3,4
输出样例:
在这里给出相应的输出,交点坐标之间以英文","分隔,判断结果与坐标之间以一个英文空格分隔。例如:
is parallel lines,have no intersection point
code
import java.util.Scanner; public class Main { public static void main(String[] args) { // TODO 自动生成的方法存根 Scanner in = new Scanner(System.in); int f = 0,f1 = 0,f2 = 0,count = 0,i,j,b1=0,d; boolean flag; double x1,x2,y1,y2,x3,y3,x4,y4,k,distance,a,b,c,e,g,x,y,h,l,a1,a2,a3,a4; String sc = in.nextLine(); d = sc.length()-1; for(i=0;i<sc.length();i++) { if(sc.charAt(i)==' ') { f = 1; } } for(i=0;i<sc.length();i++) { if(sc.charAt(i) == ':') f1++; } for(i=0;i<sc.length()-1;i++) { if(f1!=1||f==0||(sc.charAt(i)=='+'&&sc.charAt(i+1)=='+')|| (sc.charAt(i)=='-'&&sc.charAt(i+1)=='-')|| (sc.charAt(i)=='+'&&sc.charAt(i+1)=='-')|| (sc.charAt(i)=='-'&&sc.charAt(i+1)=='+')|| (sc.charAt(i)=='.'&&sc.charAt(i+1)==',')|| (sc.charAt(i)==','&&sc.charAt(i+1)=='.')|| (sc.charAt(i)==':'&&sc.charAt(i+1)==':')|| (sc.charAt(i)==':'&&sc.charAt(i+1)=='.')|| (sc.charAt(i)=='.'&&sc.charAt(i+1)==':')|| (sc.charAt(i)=='0'&&sc.charAt(i+1)=='0')|| (sc.charAt(i)=='0'&&(sc.charAt(i+1)>'0'&&sc.charAt(i+1)<'9'))|| (sc.charAt(i)==':'&&sc.charAt(i+1)==',')|| (sc.charAt(i)==':'&&sc.charAt(i+1)==' ')|| (sc.charAt(i)==','&&sc.charAt(i+1)==':')|| (sc.charAt(i)=='.'&&sc.charAt(i+1)==' ')|| (sc.charAt(i)==' '&&sc.charAt(i+1)=='.')|| (sc.charAt(i)=='.'&&sc.charAt(i+1)=='.')|| (sc.charAt(i)==' '&&sc.charAt(i+1)==',')|| (sc.charAt(i)==','&&sc.charAt(i+1)==' ')|| (sc.charAt(i)==' '&&sc.charAt(i+1)==' ')|| (sc.charAt(i)==','&&sc.charAt(i+1)==',')|| sc.charAt(0)=='.'||sc.charAt(d)=='.'||sc.charAt(0)==','|| sc.charAt(1)!=':'||sc.charAt(d)==' '||sc.charAt(d)==','|| sc.charAt(d)==':'||sc.charAt(0)<'1'||sc.charAt(0)>'5'){ b1 = 1; } } if(b1==1) { System.out.print("Wrong Format"); System.exit(0); } if(sc.charAt(0)=='1') { for(i=0;i<sc.length();i++) { if(sc.charAt(i)==' ') { count++; } } for(i=0;i<sc.length();i++) { if(sc.charAt(i)==',') { f2++; } } if(count!=1||f2!=2) { System.out.print("wrong number of points"); System.exit(0); } if(count==1&&f2==2) { String[] p=sc.split(" "); String[] m=p[0].split(":"); String[] q=m[1].split(","); String[] n=p[1].split(","); x1=Double.parseDouble(q[0]); y1=Double.parseDouble(q[1]); x2=Double.parseDouble(n[0]); y2=Double.parseDouble(n[1]); if(x1==x2&&y1==y2) { System.out.print("points coincide"); System.exit(0); } else if(x1==x2&&y1!=y2) { System.out.print("Slope does not exist"); System.exit(0); } else { k = (y1-y2)/(x1-x2); System.out.print(k); System.exit(0); } } } if(sc.charAt(0)=='2') { for(i=0;i<sc.length();i++) { if(sc.charAt(i)==' ') { count++; } } for(i=0;i<sc.length();i++) { if(sc.charAt(i)==',') { f2++; } } if(count!=2||f2!=3) { System.out.print("wrong number of points"); } if(count==2&&f2==3) { String[] p=sc.split(" "); String[] q=p[0].split(":"); String[] m=q[1].split(","); String[] n=p[1].split(","); String[] s=p[2].split(","); x1=Double.parseDouble(m[0]); y1=Double.parseDouble(m[1]); x2=Double.parseDouble(n[0]); y2=Double.parseDouble(n[1]); x3=Double.parseDouble(s[0]); y3=Double.parseDouble(s[1]); if((x1==x2&&y1==y2)||(x1==x3&&y1==y3)||(x2==x3&&y2==y3)) { System.out.print("points coincide"); } else{ distance = Math.abs((y2-y3)*x1+(x3-x2)*y1+x2*y3-y2*x3)/Math.sqrt((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3)); System.out.print(distance); } } } if(sc.charAt(0)=='3') { for(i=0;i<sc.length();i++) { if(sc.charAt(i)==' ') { count++; } } for(i=0;i<sc.length();i++) { if(sc.charAt(i)==',') { f2++; } } if(count!=2||f2!=3) { System.out.print("wrong number of points"); } if(count==2&&f2==3) { String[] p=sc.split(" "); String[] q=p[0].split(":"); String[] m=q[1].split(","); String[] n=p[1].split(","); String[] s=p[2].split(","); x1=Double.parseDouble(m[0]); y1=Double.parseDouble(m[1]); x2=Double.parseDouble(n[0]); y2=Double.parseDouble(n[1]); x3=Double.parseDouble(s[0]); y3=Double.parseDouble(s[1]); if((x1==x2&&y1==y2)||(x1==x3&&y1==y3)||(x2==x3&&y2==y3)) { System.out.print("points coincide"); } double mn = (y3 - y2) / (x3 - x2); double ab = y2 - (mn * x2); if(x1 == x3 && x1 == x2) System.out.println("true"); else if(y1 == y2 && y2 == y3) System.out.println("true"); else if(y1 == mn * x1 + ab) System.out.println("true"); else System.out.println("false"); } } if(sc.charAt(0)=='4') { for(i=0;i<sc.length();i++) { if(sc.charAt(i)==' ') { count++; } } for(i=0;i<sc.length();i++) { if(sc.charAt(i)==',') { f2++; } } if(count!=3||f2!=4) { System.out.print("wrong number of points"); } if(count==3&&f2==4) { String[] p=sc.split(" "); String[] q=p[0].split(":"); String[] m=q[1].split(","); String[] n=p[1].split(","); String[] s=p[2].split(","); String[] z=p[3].split(","); x1=Double.parseDouble(m[0]); y1=Double.parseDouble(m[1]); x2=Double.parseDouble(n[0]); y2=Double.parseDouble(n[1]); x3=Double.parseDouble(s[0]); y3=Double.parseDouble(s[1]); x4=Double.parseDouble(z[0]); y4=Double.parseDouble(z[1]); double k1 = (y2 - y1) / (x2 - x1); double k2 = (y4 - y3) / (x4 - x3); if((x1 == x2 && y1 == y2) || (x3 == x4 && y3 == y4)) System.out.println("points coincide"); else if(x1 == x2 && x3 == x4) System.out.println("true"); else if(k1 == k2) System.out.println("true"); else System.out.println("false"); } } if(sc.charAt(0)=='5') { for(i=0;i<sc.length();i++) { if(sc.charAt(i)==' ') { count++; } } for(i=0;i<sc.length();i++) { if(sc.charAt(i)==',') { f2++; } } if(count!=3||f2!=4) { System.out.print("wrong number of points"); } if(count==3&&f2==4) { String[] p=sc.split(" "); String[] q=p[0].split(":"); String[] m=q[1].split(","); String[] n=p[1].split(","); String[] s=p[2].split(","); String[] z=p[3].split(","); x1=Double.parseDouble(m[0]); y1=Double.parseDouble(m[1]); x2=Double.parseDouble(n[0]); y2=Double.parseDouble(n[1]); x3=Double.parseDouble(s[0]); y3=Double.parseDouble(s[1]); x4=Double.parseDouble(z[0]); y4=Double.parseDouble(z[1]); if((x1==x2&&y1==y2)||(x3==x4&&y4==y3)) { System.out.print("points coincide"); } else { h=Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); l=Math.sqrt((x3-x4)*(x3-x4)+(y3-y4)*(y3-y4)); double k1 = (y2 - y1) / (x2 - x1); double k2 = (y4 - y3) / (x4 - x3); if((x1 == x2 && y1 == y2) || (x3 == x4 && y3 == y4)) System.out.println("points coincide"); else if(x1 == x2 && x3 == x4) System.out.println("is parallel lines,have no intersection point"); else if(k1 == k2) System.out.println("is parallel lines,have no intersection point"); else { x=(y3*x4*x2-y4*x3*x2-y3*x4*x1+y4*x3*x1-y1*x2*x4+y2*x1*x4+y1*x2*x3-y2*x1*x3)/(x4*y2-x4*y1-x3*y2+x3*y1-x2*y4+x2*y3+x1*y4-x1*y3); y=(-y3*x4*y2+y4*x3*y2+y3*x4*y1-y4*x3*y1+y1*x2*y4-y1*x2*y3-y2*x1*y4+y2*x1*y3)/(y4*x2-y4*x1-y3*x2+x1*y3-y2*x4+y2*x3+y1*x4-y1*x3); a1=Math.sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2)); a2=Math.sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1)); a3=Math.sqrt((x-x3)*(x-x3)+(y-y3)*(y-y3)); a4=Math.sqrt((x-x4)*(x-x4)+(y-y4)*(y-y4)); if(((a1+a2)-h<=0.0001&&x!=x1&&x!=x2)||((a3+a4)-l)<=0.0001&&x!=x3&&x!=x4) { flag = true; } else { flag = false; } System.out.println((float)x+","+(float)y+" "+flag); } } } } } }
本题的难度依旧是对于字符串的处理,但是在第一题的基础上迭代下来并不是难点,难点在于对于数据的处理能力,比如对于给出的四个点,求四点形成的两条线的交点,这个需要数学能力来计算出坐标之间的关系,另外需要注意的是double类型使用会有一定的误差,对于==
的处理一般是取其差值的绝对值来与一个很小的数来比较。
-
7-3 点线形系列3-三角形的计算
用户输入一组选项和数据,进行与三角形有关的计算。选项包括:
1:输入三个点坐标,判断是否是等腰三角形、等边三角形,判断结果输出true/false,两个结果之间以一个英文空格符分隔。
2:输入三个点坐标,输出周长、面积、重心坐标,三个参数之间以一个英文空格分隔,坐标之间以英文","分隔。
3:输入三个点坐标,输出是钝角、直角还是锐角三角形,依次输出三个判断结果(true/false),以一个英文空格分隔,
4:输入五个点坐标,输出前两个点所在的直线与三个点所构成的三角形相交的交点数量,如果交点有两个,则按面积大小依次输出三角形被直线分割成两部分的面积。若直线与三角形一条线重合,输出"The point is on the edge of the triangle"
5:输入四个点坐标,输出第一个是否在后三个点所构成的三角形的内部(输出in the triangle/outof triangle)。
必须使用射线法,原理:由第一个点往任一方向做一射线,射线与三角形的边的交点(不含点本身)数量如果为1,则在三角形内部。如果交点有两个或0个,则在三角形之外。若点在三角形的某条边上,输出"on the triangle"
输入格式:
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
输出格式:
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
如果输入的三个点无法构成三角形,输出"data error"。
注意:输出的数据若小数点后超过6位,只保留小数点后6位,多余部分采用四舍五入规则进到最低位。小数点后若不足6位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333333,1.0按格式输出为1.0
选项4中所输入线的两个点坐标重合,输出"points coincide",
输入样例1:
选项4,定义线的两点重合。例如:
4:1,0 1,0 0,0 2,0 4,0
输出样例:
在这里给出相应的输出。例如:
points coincide
输入样例2:
选项4,构成三角形的三个点在一条线上,无法构成三角形。例如:
4:1,0 0,2 0,0 0,0 4,0
输出样例:
在这里给出相应的输出。例如:
data error
输入样例3:
选项1,判断等腰、等边三角形。例如:
1:-2,0 2,0 0,4
输出样例:
两个判断结果。例如:
true false
输入样例4:
选项2,输出边长、面积、重心坐标。例如:
2:0,0 3,0 0,1
输出样例:
在这里给出相应的输出。例如:
7.162278 1.5 1.0,0.333333
输入样例5:
选项3,钝角、直角、锐角的判断。例如:
3:0,1 1,0 2,0
输出样例:
在这里给出相应的输出。例如:
true false false
输入样例6:
选项4,直线与三角形交点的数量等于2,输出数量值以及三角形被分割的两部分面积。例如:
4:1,0 0,2 0,0 0,2 4,0
输出样例:
在这里给出相应的输出。例如:
2 1.0 3.0
输入样例7:
选项4,直线与三角形交点的数量少于两个,只输出数量值。例如:
4:-1,0 1,2 0,1 0,-1 2,0
输出样例:
在这里给出相应的输出。例如:
1
输入样例8:
选项5,用射线法判断点是否在三角形内部。例如:
5:0.5,0.5 0,0 0,2 4,0
输出样例:
在这里给出相应的输出,交点坐标之间以英文","分隔,判断结果与坐标之间以一个英文空格分隔。例如:
in the triangle
输入样例9:
选项5,用射线法判断点是否在三角形内部。例如:
5:0,0 -1,-1 2,3 3,4
输出样例:
在这里给出相应的输出。例如:
outof the triangle
code
import java.util.Scanner; public class Main { public static void main(String[] args) { char choice; Scanner input = new Scanner(System.in); String enter = input.nextLine(); choice = enter.charAt(0); if ((choice < '1' || choice > '5') || enter.charAt(1) != ':') { System.out.println("Wrong Format"); System.exit(0); } if (choice == '1') { boolean flag1,flag2; if (blanksum(enter) == 0) { System.out.println("Wrong Format"); System.exit(0); } else if (blanksum(enter) != 2 && comsum(enter) != 3) { System.out.println("wrong number of points"); System.exit(0); } else if (blanksum(enter) == 2) { String[] p1 = enter.split(" "); String[] p2 = p1[0].split(":"); String[] point1xy = p2[1].split(","); String[] point2xy = p1[1].split(","); String[] point3xy = p1[2].split(","); Point point1 = new Point(Double.parseDouble(point1xy[0]), Double.parseDouble(point1xy[1])); Point point2 = new Point(Double.parseDouble(point2xy[0]), Double.parseDouble(point2xy[1])); Point point3 = new Point(Double.parseDouble(point3xy[0]), Double.parseDouble(point3xy[1])); if (triangle(point1.getX(),point1.getY(),point2.getX(),point2.getY(),point3.getX(),point3.getY())) { flag1 = point1.isosceles(point2, point3);//等腰 flag2 = point1.equilateral(point2, point3);//等边 if(flag1) { System.out.print("true "); if(flag2) { System.out.print("true"); }else { System.out.print("false"); } }else { System.out.print("false false"); } } else { System.out.println("data error"); System.exit(0); } } } if (choice == '2') { double x0,y0; double ab,ac,bc; double circumference,area,p; if (blanksum(enter) == 0) { System.out.println("Wrong Format"); System.exit(0); } // else if (format(enter) == false) { // System.out.println("Wrong Format"); // System.exit(0); // } else if (blanksum(enter) != 2 && comsum(enter) != 3) { System.out.println("wrong number of points"); System.exit(0); } else if (blanksum(enter) == 2) { String[] p1 = enter.split(" "); String[] p2 = p1[0].split(":"); String[] point1xy = p2[1].split(","); String[] point2xy = p1[1].split(","); String[] point3xy = p1[2].split(","); Point point1 = new Point(Double.parseDouble(point1xy[0]), Double.parseDouble(point1xy[1])); Point point2 = new Point(Double.parseDouble(point2xy[0]), Double.parseDouble(point2xy[1])); Point point3 = new Point(Double.parseDouble(point3xy[0]), Double.parseDouble(point3xy[1])); if (triangle(point1.getX(),point1.getY(),point2.getX(),point2.getY(),point3.getX(),point3.getY())) { x0 = (point1.getX()+point2.getX()+point3.getX())/3; y0 = (point1.getY()+point2.getY()+point3.getY())/3; ab = Math.sqrt((point2.getY() - point1.getY()) * (point2.getY() - point1.getY()) + (point2.getX()-point1.getX()) * (point2.getX()-point1.getX())); ac = Math.sqrt((point3.getY() - point1.getY()) * (point3.getY() - point1.getY()) + (point3.getX()-point1.getX()) * (point3.getX()-point1.getX())); bc = Math.sqrt((point3.getY() - point2.getY()) * (point3.getY() - point2.getY()) + (point3.getX()-point2.getX()) * (point3.getX()-point2.getX())); circumference=ab+ac+bc; p = circumference / 2; area = Math.sqrt(p*(p-ab)*(p-ac)*(p-bc)); circumference = Math.round(circumference*1000000)/1000000.0; area = Math.round(area*1000000)/1000000.0; x0 = Math.round(x0*1000000)/1000000.0; y0 = Math.round(y0*1000000)/1000000.0; System.out.println(circumference+" "+area+" "+x0+","+y0); System.exit(0); } else { System.out.println("data error"); System.exit(0); } } } if (choice == '3') { double ab,ac,bc,temp,a,b,c; boolean flag1,flag2,flag3; if (blanksum(enter) == 0) { System.out.println("Wrong Format"); System.exit(0); } // else if (format(enter) == false) { // System.out.println("Wrong Format"); // System.exit(0); // } else if (blanksum(enter) != 2 && comsum(enter) != 3) { System.out.println("wrong number of points"); System.exit(0); } else if (blanksum(enter) == 2) { String[] p1 = enter.split(" "); String[] p2 = p1[0].split(":"); String[] point1xy = p2[1].split(","); String[] point2xy = p1[1].split(","); String[] point3xy = p1[2].split(","); Point point1 = new Point(Double.parseDouble(point1xy[0]), Double.parseDouble(point1xy[1])); Point point2 = new Point(Double.parseDouble(point2xy[0]), Double.parseDouble(point2xy[1])); Point point3 = new Point(Double.parseDouble(point3xy[0]), Double.parseDouble(point3xy[1])); if (triangle(point1.getX(),point1.getY(),point2.getX(),point2.getY(),point3.getX(),point3.getY())) { ab = Math.sqrt((point2.getY() - point1.getY()) * (point2.getY() - point1.getY()) + (point2.getX()-point1.getX()) * (point2.getX()-point1.getX())); ac = Math.sqrt((point3.getY() - point1.getY()) * (point3.getY() - point1.getY()) + (point3.getX()-point1.getX()) * (point3.getX()-point1.getX())); bc = Math.sqrt((point3.getY() - point2.getY()) * (point3.getY() - point2.getY()) + (point3.getX()-point2.getX()) * (point3.getX()-point2.getX())); if(ab>bc) { temp = ab; ab = bc; bc = temp; } if(ab>ac) { temp = ab; ab = ac; ac = temp; } if(bc>ac) { temp = bc; bc = ac; ac = temp; } a = ab; b = bc; c = ac; if(Math.abs(a*a+b*b-c*c)<0.000001) {//直角判断 flag1 = true; }else { flag1 = false; } if(a*a+b*b-c*c>0) {//锐角判断 flag2 = true; }else { flag2 = false; } if(a*a+b*b-c*c<-0.00001) {//钝角判断 flag3 = true; }else { flag3 = false; } System.out.println(flag3+" "+flag1+" "+flag2); System.exit(0); } else { System.out.println("data error"); System.exit(0); } } } if (choice == '4') { if (blanksum(enter) == 0) { System.out.println("Wrong Format"); System.exit(0); } else if (format(enter) == false) { System.out.println("Wrong Format"); System.exit(0); } else if (blanksum(enter) != 4 && comsum(enter) != 5) { System.out.println("wrong number of points"); System.exit(0); } else if (blanksum(enter) == 4) { String[] p1 = enter.split(" "); String[] p2 = p1[0].split(":"); String[] point1xy = p2[1].split(","); String[] point2xy = p1[1].split(","); String[] point3xy = p1[2].split(","); String[] point4xy = p1[3].split(","); String[] point5xy = p1[4].split(","); Point point1 = new Point(Double.parseDouble(point1xy[0]), Double.parseDouble(point1xy[1])); Point point2 = new Point(Double.parseDouble(point2xy[0]), Double.parseDouble(point2xy[1])); Point point3 = new Point(Double.parseDouble(point3xy[0]), Double.parseDouble(point3xy[1])); Point point4 = new Point(Double.parseDouble(point4xy[0]), Double.parseDouble(point4xy[1])); Point point5 = new Point(Double.parseDouble(point5xy[0]), Double.parseDouble(point5xy[1])); if(point1.getX()==point2.getX()&&point1.getY()==point2.getY()) { System.out.println("points coincide"); System.exit(0); }else { if (triangle(point3.getX(),point3.getY(),point4.getX(),point4.getY(),point5.getX(),point5.getY())) { // if(point3.collinear(point1, point2)||point4.collinear(point1, point2)||point5.collinear(point1, point2)) { // System.out.println("1"); // System.exit(0); // } if(point1.lineslope(point2)==point5.lineslope(point3)&&point3.pointline(point1, point2)==0) { System.out.println("The point is on the edge of the triangle"); System.exit(0); } if(point1.lineslope(point2)==point5.lineslope(point4)&&point4.pointline(point1, point2)==0) { System.out.println("The point is on the edge of the triangle"); System.exit(0); } if(point1.lineslope(point2)==point3.lineslope(point4)&&point3.pointline(point1, point2)==0) { System.out.println("The point is on the edge of the triangle"); System.exit(0); } else { Point intsect1 = new Point(); Point intsect2 = new Point(); Point intsect3 = new Point(); intsect1 = point1.interline(point2, point3, point5); intsect2 = point1.interline(point2, point3, point4); intsect3 = point1.interline(point2, point4, point5); if(!intsect1.inline(point3, point5)&&!intsect2.inline(point3, point4)&&!intsect3.inline(point4, point5)) { System.out.println("0"); System.exit(0); } if((intsect1.getX()==intsect2.getX()&&intsect1.getY()==intsect2.getY()&&!intsect3.inline(point4, point5))||(intsect1.getX()==intsect3.getX()&&intsect1.getY()==intsect3.getY()&&!intsect2.inline(point3, point4))||(intsect2.getX()==intsect3.getX()&&intsect2.getY()==intsect3.getY()&&!intsect1.inline(point3, point5))) { System.out.println("1"); System.exit(0); }else { if(intsect1.inline(point3, point5)&&intsect3.inline(point4, point5)) { double area1 = point5.area(intsect1, intsect3); double area2 = point3.area(point4, point5)-area1; if(area1<area2) { double temp = area1; area1 = area2; area2 = temp; } area1 = Math.round(area1*1000000)/1000000.0; area2 = Math.round(area2*1000000)/1000000.0; System.out.println(2+" "+area2+" "+area1); System.exit(0); } if(intsect1.inline(point3, point5)&&intsect2.inline(point3, point4)&&(intsect1.getX()!=intsect3.getX())) { double area1 = point3.area(intsect1, intsect2); double area2 = point3.area(point4, point5)-area1; if(area1<area2) { double temp = area1; area1 = area2; area2 = temp; } area1 = Math.round(area1*1000000)/1000000.0; area2 = Math.round(area2*1000000)/1000000.0; System.out.println(2+" "+area2+" "+area1); System.exit(0); } if(intsect2.inline(point3, point4)&&intsect3.inline(point4, point5)) { double area1 = point4.area(intsect2, intsect3); double area2 = point3.area(point4, point5)-area1; if(area1<area2) { double temp = area1; area1 = area2; area2 = temp; } area1 = Math.round(area1*1000000)/1000000.0; area2 = Math.round(area2*1000000)/1000000.0; System.out.println(2+" "+area2+" "+area1); System.exit(0); } } } } else { System.out.println("data error"); System.exit(0); } } } } if (choice == '5') { int count = 0; if (blanksum(enter) == 0) { System.out.println("Wrong Format"); System.exit(0); } // else if (format(enter) == false) { // System.out.println("Wrong Format"); // System.exit(0); // } else if (blanksum(enter) != 3 && comsum(enter) != 4) { System.out.println("wrong number of points"); System.exit(0); } else if (blanksum(enter) == 3) { String[] p1 = enter.split(" "); String[] p2 = p1[0].split(":"); String[] point1xy = p2[1].split(","); String[] point2xy = p1[1].split(","); String[] point3xy = p1[2].split(","); String[] point4xy = p1[3].split(","); Point point1 = new Point(Double.parseDouble(point1xy[0]), Double.parseDouble(point1xy[1])); Point point2 = new Point(Double.parseDouble(point2xy[0]), Double.parseDouble(point2xy[1])); Point point3 = new Point(Double.parseDouble(point3xy[0]), Double.parseDouble(point3xy[1])); Point point4 = new Point(Double.parseDouble(point4xy[0]), Double.parseDouble(point4xy[1])); if (triangle(point2.getX(),point2.getY(),point3.getX(),point3.getY(),point4.getX(),point4.getY())) { Point intsection1 = new Point(); Point intsection2 = new Point(); Point intsection3 = new Point(); if(point1.inline(point2, point3)||point1.inline(point2, point4)||point1.inline(point3, point4)) { System.out.println("on the triangle"); System.exit(0); } if((point1.getX()==point2.getX()&&point1.getY()==point2.getY())||(point1.getX()==point3.getX()&&point1.getY()==point3.getY())||(point1.getX()==point4.getX()&&point1.getY()==point4.getY())) { System.out.println("on the triangle"); System.exit(0); } Point ray = new Point(1000,point1.getY()+20); if(ray.Parallelline(point1, point2, point4)) { intsection1.setX(point1.getX()); intsection1.setY(point1.getY()); }else { intsection1 = point1.interline(ray, point2, point4); } intsection2 = point1.interline(ray, point2, point3); intsection3 = point1.interline(ray, point3, point4); if(intsection1.getX()>point1.getX()) { count++; } if(intsection2.getX()>point1.getX()) { count++; } if(intsection3.getX()>point1.getX()) { count++; } if(count==1) { System.out.println("in the triangle"); System.exit(0); } if(count==0||count==2) { System.out.println("outof the triangle"); System.exit(0); } } else { System.out.println("data error"); System.exit(0); } } } } public static boolean format(String S) { boolean flag = true; for (int i = 0; i < S.length() - 1; i++) { if ((S.charAt(i) == '+' && S.charAt(i + 1) == '+') || (S.charAt(i) == '-' && S.charAt(i + 1) == '-') || (S.charAt(i) == '+' && S.charAt(i + 1) == '-') || (S.charAt(i) == '-' && S.charAt(i + 1) == '+') || (S.charAt(i) == '.' && S.charAt(i + 1) == ',') || (S.charAt(i) == ',' && S.charAt(i + 1) == '.') // || (S.charAt(i) == '.' && S.charAt(i + 1) == ' ') || (S.charAt(i) == '0' && S.charAt(i + 1) == '0') || (S.charAt(i) == ' ' && S.charAt(i + 1) == '.') || (S.charAt(i) == '.' && S.charAt(i + 1) == '.') || (S.charAt(i) == ' ' && S.charAt(i + 1) == ',') || (S.charAt(i) == ',' && S.charAt(i + 1) == ' ') || (S.charAt(i) == ' ' && S.charAt(i + 1) == ' ') || (S.charAt(i) == ':' && S.charAt(i + 1) == ':') || (S.charAt(i) == ',' && S.charAt(i + 1) == ',') || (S.charAt(S.length() - 1) == ',') || (S.charAt(i) == ':' && S.charAt(i + 1) == ',') || (S.charAt(i) == '0' && (S.charAt(i + 1) > '0' && S.charAt(i + 1) < '9')) || (S.charAt(i) == ':' && S.charAt(i + 1) == '.')) { flag = false; } } return flag; } public static int blanksum(String S) { int count = 0; for (int i = 0; i < S.length(); i++) { if (S.charAt(i) == ' ') { count++; } } return count; } public static int comsum(String S) { int count = 0; for (int i = 0; i < S.length(); i++) { if (S.charAt(i) == ',') { count++; } } return count; } public static boolean triangle(double x1,double y1,double x2,double y2,double x3,double y3) { boolean flag=true; double AB, AC, BC; AB = Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1)); AC = Math.sqrt((y3- y1) * (y3 - y1) + (x3 - x1) * (x3 - x1)); BC = Math.sqrt((y3 - y2) * (y3 - y2) + (x3 - x2) * (x3 - x2)); if(AB+BC<=AC||BC+AC<=AB||AB+BC<=AB) { flag=false; } return flag; } } class Point { private double x, y; public Point() { super(); // TODO 自动生成的构造函数存根 } public Point(double x, double y) { super(); this.x = x; this.y = y; } public double getX() { return x; } public void setX(double x) { this.x = x; } public double getY() { return y; } public void setY(double y) { this.y = y; } public boolean isosceles(Point p2, Point p3) {// 判断是否为等腰三角形 boolean flag = false; double AB, AC, BC; AB = Math.sqrt((p2.y - y) * (p2.y - y) + (p2.x - x) * (p2.x - x)); AC = Math.sqrt((p3.y - y) * (p3.y - y) + (p3.x - x) * (p3.x - x)); BC = Math.sqrt((p3.y - p2.y) * (p3.y - p2.y) + (p3.x - p2.x) * (p3.x - p2.x)); if ((AB == AC ) || (AB == BC ) || (AC == BC )) { flag = true; } return flag; } public boolean equilateral(Point p2, Point p3) {// 判断是否为等边三角形 boolean flag = false; double AB, AC, BC; AB = Math.sqrt((p2.y - y) * (p2.y - y) + (p2.x - x) * (p2.x - x)); AC = Math.sqrt((p3.y - y) * (p3.y - y) + (p3.x - x) * (p3.x - x)); BC = Math.sqrt((p3.y - p2.y) * (p3.y - p2.y) + (p3.x - p2.x) * (p3.x - p2.x)); if (AB == BC && AB == AC ) { flag = true; } return flag; } public boolean collinear(Point p1, Point p2) {// 三点共线 boolean flag = true; if ((p1.x - x) * (p2.y - p1.y) != (p2.x - p1.x) * (p1.y - y)) { flag = false; } return flag; } public double pointline(Point p1, Point p2) {// 点线距 double A, B, C, distance; B = p1.x - p2.x; A = p2.y - p1.y; C = p1.x * (p1.y - p2.y) - p1.y * (p1.x - p2.x); distance = (Math.abs(A * x + B * y + C)) / (Math.sqrt(A * A + B * B)); return distance; } public double lineslope(Point p) { double slope; slope = (p.y - y) / (p.x - x); return slope; } public Point interline(Point p1, Point p2, Point p3) { Point sectionpoint = new Point(); double x0, y0; x0 = (p2.y * p3.x * p1.x - p3.y * p2.x * p1.x - p2.y * p3.x * x + p3.y * p2.x * x - y * p1.x * p3.x + p1.y * x * p3.x + y * p1.x * p2.x - p1.y * x * p2.x) / (p3.x * p1.y - p3.x * y - p2.x * p1.y + p2.x * y - p1.x * p3.y + p1.x * p2.y +x * p3.y - x * p2.y); y0 = (-p2.y * p3.x * p1.y + p3.y * p2.x * p1.y + p2.y * p3.x * y - p3.y * p2.x * y + y * p1.x * p3.y - y * p1.x * p2.y - x * p1.y * p3.y + p1.y * x * p2.y) / (p3.y * p1.x - p3.y * x - p2.y * p1.x + x * p2.y - p1.y * p3.x + p1.y * p2.x + y * p3.x - y * p2.x); sectionpoint.setX(x0); sectionpoint.setY(y0); return sectionpoint; } public boolean Parallelline(Point p1, Point p2, Point p3) {// 四点两线平行 boolean flag = false; double k1, k2; k1 = (p1.y - y) / (p1.x - x); k2 = (p3.y - p2.y) / (p3.x - p2.x); if(p1.x==x&&p3.x==p2.x){ flag = true; } if (k1 == k2) { flag = true; } return flag; } public double area(Point p1,Point p2) { double ab,ac,bc; double circumference,area,p; ab = Math.sqrt((p2.getY() - y) * (p2.getY() - y) + (p2.getX()-x) * (p2.getX()-x)); ac = Math.sqrt((p1.getY() - y) * (p1.getY() -y) + (p1.getX()-x) * (p1.getX()-x)); bc = Math.sqrt((p1.getY() - p2.getY()) * (p1.getY() - p2.getY()) + (p1.getX()-p2.getX()) * (p1.getX()-p2.getX())); circumference=ab+ac+bc; p = circumference / 2; area = Math.sqrt(p*(p-ab)*(p-ac)*(p-bc)); return 0.5 * Math.abs(x * p2.getY() + p1.getX() * y + p2.getX() * p1.getY() - x * p1.getY() - p1.getX() * p2.getY() -p2.getX() * y); }; public boolean inline(Point p1, Point p2) { boolean flag = false; double distance1 = Math.sqrt((p2.y - p1.y) * (p2.y - p1.y) + (p2.x - p1.x) * (p2.x - p1.x)); double distance2 = Math.sqrt((p2.y - y) * (p2.y - y) + (p2.x - x) * (p2.x - x)) + Math.sqrt((p1.y - y) * (p1.y - y) + (p1.x - x) * (p1.x - x)); if (distance1 + 0.00001 > distance2) flag = true; return flag; } }
本题是这次题目集中难度最高的题,难度在于数据的处理,选项一判断是否为等腰三角形和等边三角形,判断的依据为三角形的三条边,如果存在两条边相等则判断为等腰三角形,如果三条边都相等判断为等边三角形,虽然方法简单但确实好用,有时候适合用于计算机判断的方法,往往是一些简单的定理;在第二个选项中需要对数据进行四舍五入同时保留六位小数的处理,在这里我采用的是Math.round()
四舍五入,但当参数为负数时不太好理解,注意返回的是整型所以需要处理成小数形式。这里有一些四舍五入的方法可以参考:Java Math floor、ceil、rint 及 round 用法 ;第三个选项需要注意的是判断三角形类型的时候存在误差,这里我采取的是利用三条边的关系来判断三角形类型但是在判断直角和钝角的时候出现了误差,有一组数据被同时判断为直角和钝角,所以在后面我给判断条件加上了具有一定误差的处理;第四个选项中面积的算法是最复杂的,因为分割情况的不同,所采用的面积计算方式也不一样,在这些分割情况中一般都是分割为一个小三角形和四边形,但是在计算三角形面积的时候需要确定三角形的顶点然后利用海伦公式来计算面积;第五个选项中了解到了射线法,在这里实现射线法的原理是利用自己设的一个点与给出的点连成一条线,然后计算交点,在比较交点与给出点的位置,从而得到交点的个数来判断给出点的位置。
SourceMonitor的生成报表内容
在这里我们可以看出代码的复杂度和深度都非常高,这是因为没有合理的使用类,在本题中我只使用了一个点类,对于线类是包含在了点类,这种做法是错误的,我们可以参考一下老师给出的类图
可以看出老师给出的代码结构很合理,所以在后续的学习过程中,应该先思考画图,理清逻辑之后再去实现,以保证代码质量。
双向链表练习
在单链表基础上改写代码,实现双向链表数据结构:
public class Node<E> { private E data;//数据域,类型为泛型E private Node<E> next;//后继引用(指针) private Node<E> previous;//前驱引用(指针) } public interface DoubleLinkedListImpl<E> { /** * 判断链表是否为空 * @return */ public boolean isEmpty(); /** * 获取当前链表节点数量 * @return 节点数 */ public int getSize(); /** * 获取链表中第index个位置的节点的data值 * @param index:节点在链表中的位置 * @return:返回该节点的data值 */ public E getData(int index); /** * 删除链表最后一个节点 */ public void remove(); /** *删除链表中第index位置的节点 * @param index:节点在链表中的位置 */ public void remove(int index); /** * 在链表的第index个位置之前插入一个节点,值为theElement,index∈[1,size] * @param index:插入节点在链表中的位置 * @param theElement:新插入节点的data值 */ public void add(int index, E theElement); /** * 在链表尾插入节点,插入节点data值为element * @param element */ public void add(E element) /** * 输出链表 */ public void printList(); /** * 获取第一个节点的data值 * @return */ public E getFirst(); /** * 获取链表最后一个节点的data值 * @return */ public E getLast(); } public class DoubleLinkedList<E> implements DoubleLinkedListImpl<E> { private Node<E> head;//头结点,非第一个节点 private Node<E> curr;//当前节点 private Node<E> tail;//最后一个节点 private int size;//当前链表节点数 ...... }
code
public class DoubleLinkedList<E> implements DoubleLinkedListImpl<E> { private Node<E> head;// 头结点(非第一个节点),当前节点,尾节点 private Node<E> curr; private Node<E> tail; private int size = 0; public DoubleLinkedList() { super(); // TODO Auto-generated constructor stub head = new Node<E>(); head.setNext(null); head.setPrior(null); curr = tail = null; this.size = 0; } @Override public boolean isEmpty() { // TODO Auto-generated method stub return this.size == 0; } @Override public int getSize() { // TODO Auto-generated method stub return this.size; } @Override public E get(int index) { // TODO Auto-generated method stub if(index < 1 || index > this.size) { return null; } curr = head; if(index>this.size>>1) { curr = tail; for(int i = size ;i>index;i--) { curr = curr.getPrior(); } } else { for(int i = 0 ;i<index;i++) { curr = curr.getNext(); } } return curr.getData(); } @Override public void remove(int index) { // TODO Auto-generated method stub if(index < 1 || index > this.size) { return ; } if(head.getNext()==null) { System.out.println("链表为空"); return ; } curr = head; if(index == 1) { curr = head.getNext(); head.setNext(curr.getNext()); curr.getNext().setPrior(head); } if(index == this.size) {//如果删除的是最后一个节点 tail = curr; } else {//找到第index - 1个节点赋给curr for(int i = 1;i < index; i++) { curr = curr.getNext(); } curr.setNext(curr.getNext().getNext()); curr.getNext().setPrior(curr); } this.size --;//整个链表的节点数量-1 } @Override public void add(int index, E theElement) { // TODO Auto-generated method stub if(index < 1 || index > this.size + 1) { return ; } Node<E> curr = new Node<>(); curr.setData(theElement); curr.setNext(null); if(this.size == 0) {//头节点 head.setNext(curr); curr.setPrior(head); tail = curr; }else if(index == this.size + 1) {// this.tail.setNext(curr); curr.setPrior(tail); tail = curr; }else { Node<E> tempNode = head; for(int i = 0; i < index;i++) { tempNode = tempNode.getNext(); } curr.setNext(tempNode); curr.setPrior(tempNode.getPrior()); tempNode.setPrior(curr); curr.getPrior().setNext(curr); } this.size ++; } @Override public void add(E element) { // TODO Auto-generated method stub this.add(this.size + 1,element); } @Override public void headPrintList() { // TODO Auto-generated method stub curr = head.getNext(); for(int i = 1; i <= this.size;i ++) { System.out.print(curr.getData() + " "); curr = curr.getNext(); } System.out.println(""); } public void tailPrintList() { // TODO Auto-generated method stub curr = tail; for(int i = this.size; i >0;i --) { System.out.print(curr.getData() + " "); curr = curr.getPrior(); } System.out.println(""); } public E getLast() { if(this.size != 0) { return tail.getData(); } return null; } public E getFirst() { if(this.size != 0) { return head.getNext().getData(); } return null; } } public interface DoubleLinkedListImpl<E> { public boolean isEmpty(); public int getSize(); public E get(int index); public void remove(int index); public void add(int index, E theElement); public void add(E element); public void headPrintList(); public void tailPrintList(); } import java.util.Scanner; public class Main { public static void main(String[] args) { System.out.println(" ----------请输入你想进行的操作----------"); System.out.println(" ----------1:增加元素(正向)-----------------"); System.out.println(" ----------2:在指定位置增加元素(正向)-------"); System.out.println(" ----------3:查找指定位置的元素值(正向)---- "); System.out.println(" ----------4:移除指定位置的元素(正向)------ "); System.out.println(" ----------5:输出列表大小------------- "); System.out.println(" ----------6:退出程序 --------------"); int choice = 0,index = 0; int element = 0; DoubleLinkedList<Integer> list = new DoubleLinkedList<Integer>(); Scanner input = new Scanner(System.in); while(true) { System.out.println("请输入你的选择:"); choice = input.nextInt(); switch(choice) { case 1: System.out.println("请输入增加的值:"); element = input.nextInt(); list.add(element); list.headPrintList(); System.out.println();break; case 2: System.out.println("请输入指定下标和增加的值:"); index = input.nextInt(); element = input.nextInt(); list.add(index, element); list.headPrintList(); System.out.println();break; case 3: System.out.println("请输入指定下标:"); index = input.nextInt(); if(list.get(index)==null) { System.out.println("Not Found"); }else { System.out.println("这个节点的值为"+list.get(index)); } break; case 4: System.out.println("请输入指定下标:"); index = input.nextInt(); if(list.get(index)==null) { System.out.println("Not Found"); }else { list.remove(index); } list.headPrintList(); System.out.println(); break; case 5:System.out.println("这个列表的长度为"+list.getSize());break; case 6:System.exit(0);break; } } } } //Node public class Node<E> { private E data; private Node<E> next; private Node<E> prior; public Node(E data, Node<E> next, Node<E> prior) { super(); this.data = data; this.next = next; this.prior = prior; } public Node() { super(); // TODO 自动生成的构造函数存根 } public E getData() { return data; } public Node<E> getNext() { return next; } public Node<E> getPrior() { return prior; } public void setData(E data) { this.data = data; } public void setNext(Node<E> next) { this.next = next; } public void setPrior(Node<E> prior) { this.prior = prior; } }
在实现双向链表时先了解一下什么是链表:
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
链表可分为单向链表和双向链表。
一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。
一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接。
Java LinkedList(链表) 类似于 ArrayList,是一种常用的数据容器。
与 ArrayList 相比,LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低。
下面以一些图解来了解这些功能实现的原理:
在实现双向链表功能时先理清节点之间的关系才能保证功能不会出错,所以在实现之前画图是必要的,在这里需要注意的是一些边界值,比如删除第一个节点和删除最后一个节点,刚开始删除第一个节点之后打印整个链表会出现未删除成功,或者删除了第二个节点,后面发现是因为节点的连接有问题。
21级软件工程专业期中考试(OOP)
-
7-1 点与线(类设计)
设计一个类表示平面直角坐标系上的点Point,私有属性分别为横坐标x与纵坐标y,数据类型均为实型数,除构造方法以及属性的getter与setter方法外,定义一个用于显示信息的方法display(),用来输出该坐标点的坐标信息,格式如下:(x,y)
,数值保留两位小数。为简化题目,其中,坐标点的取值范围设定为(0,200]
。若输入有误,系统则直接输出Wrong Format
设计一个类表示平面直角坐标系上的线Line,私有属性除了标识线段两端的点point1、point2外,还有一个字符串类型的color,用于表示该线段的颜色,同样,除构造方法以及属性的getter与setter方法外,定义一个用于计算该线段长度的方法getDistance(),还有一个用于显示信息的方法display(),用来输出线段的相关信息,输出格式如下:
``` The line's color is:颜色值 The line's begin point's Coordinate is: (x1,y1) The line's end point's Coordinate is: (x2,y2) The line's length is:长度值 ```
其中,所有数值均保留两位小数,建议可用String.format("%.2f", data)
方法。
设计类图如下图所示。
** 题目要求:在主方法中定义一条线段对象,从键盘输入该线段的起点坐标与终点坐标以及颜色,然后调用该线段的display()方法进行输出。**
- 以下情况为无效作业
- 无法运行
- 设计不符合所给类图要求
- 未通过任何测试点测试
- 判定为抄袭
输入格式:
分别输入线段的起点横坐标、纵坐标、终点的横坐标、纵坐标以及颜色,中间可用一个或多个空格、tab或者回车分隔。
输出格式:
The line's color is:颜色值 The line's begin point's Coordinate is: (x1,y1) The line's end point's Coordinate is: (x2,y2) The line's length is:长度值
输入样例1:
在这里给出一组输入。例如:
5 9.4 12.3 84 Red
输出样例1:
在这里给出相应的输出。例如:
The line's color is:Red The line's begin point's Coordinate is: (5.00,9.40) The line's end point's Coordinate is: (12.30,84.00) The line's length is:74.96
输入样例2:
在这里给出一组输入。例如:
80.2356 352.12 24.5 100 Black
输出样例2:
在这里给出相应的输出。例如:
Wrong Format
code
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); // TODO 自动生成的方法存根 double x1,y1,x2,y2; String color; x1 = input.nextDouble(); y1 = input.nextDouble(); x2 = input.nextDouble(); y2 = input.nextDouble(); color = input.next(); if((x1<0||x1>200)||(y1<0||y1>200)||(x2<0||x2>200)||(y2<0||y2>200)) { System.out.println("Wrong Format"); System.exit(0); } Point point1 = new Point(x1,y1); Point point2 = new Point(x2,y2); Line line = new Line(point1,point2,color); line.display(); } } class Point{ private double x,y; public Point() { super(); // TODO 自动生成的构造函数存根 } public Point(double x, double y) { super(); this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } public void setX(double x) { this.x = x; } public void setY(double y) { this.y = y; } public void display() { System.out.println("("+String.format("%.2f", x)+","+String.format("%.2f", y)+")"); } } class Line{ private Point point1,point2; private String color; public Line() { super(); // TODO 自动生成的构造函数存根 } public Line(Point point1, Point point2, String color) { super(); this.point1 = point1; this.point2 = point2; this.color = color; } public Point getPoint1() { return point1; } public Point getPoint2() { return point2; } public String getColor() { return color; } public void setPoint1(Point point1) { this.point1 = point1; } public void setPoint2(Point point2) { this.point2 = point2; } public void setColor(String color) { this.color = color; } public double getDistance() { double linelength; linelength = Math.sqrt( (point2.getY() - point1.getY()) * (point2.getY() - point1.getY()) + (point2.getX() - point1.getX()) * (point2.getX() - point1.getX())); return linelength; } public void display() { System.out.println("The line's color is:"+this.color); System.out.println("The line's begin point's Coordinate is:"); point1.display(); System.out.println("The line's end point's Coordinate is:"); point2.display(); System.out.println("The line's length is:"+String.format("%.2f", getDistance())); } }
本题根据类图实现功能难度不高,实现起来比较容易,在这里需要注意的是输出格式的控制,题目的建议是使用String.format("%.2f", data)
方法,关于这个方法的使用可以点击这个链接了解:字符串格式化另外需要注意的是根据类图实现功能的题目必须按照类图一丝不差的实现,不能私自改变内容,甚至是类名,方法名。
-
7-2 点线面问题重构(继承与多态)
在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。
- 对题目中的点Point类和线Line类进行进一步抽象,定义一个两个类的共同父类Element(抽象类),将display()方法在该方法中进行声明(抽象方法),将Point类和Line类作为该类的子类。
- 再定义一个Element类的子类面Plane,该类只有一个私有属性颜色color,除了构造方法和属性的getter、setter方法外,display()方法用于输出面的颜色,输出格式如下:
The Plane's color is:颜色
- 在主方法内,定义两个Point(线段的起点和终点)对象、一个Line对象和一个Plane对象,依次从键盘输入两个Point对象的起点、终点坐标和颜色值(Line对象和Plane对象颜色相同),然后定义一个Element类的引用,分别使用该引用调用以上四个对象的display()方法,从而实现多态特性。示例代码如下:
element = p1;//起点Point element.display(); element = p2;//终点Point element.display(); element = line;//线段 element.display(); element = plane;//面 element.display();
其中,所有数值均保留两位小数,建议可用String.format("%.2f", data)
方法。
- 以下情况为无效作业
- 无法运行
- 设计不符合所给类图要求
- 未通过任何测试点测试
- 判定为抄袭
输入格式:
分别输入线段的起点横坐标、纵坐标、终点的横坐标、纵坐标以及颜色,中间可用一个或多个空格、tab或者回车分隔。
输出格式:
(x1,y1) (x2,y2) The line's color is:颜色值 The line's begin point's Coordinate is: (x1,y1) The line's end point's Coordinate is: (x2,y2) The line's length is:长度值 The Plane's color is:颜色值
输入样例1:
在这里给出一组输入。例如:
5 9.4 12.3 84 Red
输出样例1:
在这里给出相应的输出。例如:
(5.00,9.40) (12.30,84.00) The line's color is:Red The line's begin point's Coordinate is: (5.00,9.40) The line's end point's Coordinate is: (12.30,84.00) The line's length is:74.96 The Plane's color is:Red
输入样例2:
在这里给出一组输入。例如:
5 9.4 12.3 845 Black
输出样例2:
在这里给出相应的输出。例如:
Wrong Format
code
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); // TODO 自动生成的方法存根 double x1, y1, x2, y2; String color; x1 = input.nextDouble(); y1 = input.nextDouble(); x2 = input.nextDouble(); y2 = input.nextDouble(); color = input.next(); if ((x1 < 0 || x1 > 200) || (y1 < 0 || y1 > 200) || (x2 < 0 || x2 > 200) || (y2 < 0 || y2 > 200)) { System.out.println("Wrong Format"); System.exit(0); } Point point1 = new Point(x1, y1); Point point2 = new Point(x2, y2); Line line = new Line(point1, point2, color); Plane plane = new Plane(color); Element element = new Element(); element = point1;//起点Point element.display(); element = point2;//终点Point element.display(); element = line;//线段 element.display(); element = plane;//面 element.display(); } } class Point extends Element { private double x, y; public Point() { super(); // TODO 自动生成的构造函数存根 } public Point(double x, double y) { super(); this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } public void setX(double x) { this.x = x; } public void setY(double y) { this.y = y; } public void display() { System.out.println("(" + String.format("%.2f", x) + "," + String.format("%.2f", y) + ")"); } } class Line extends Element { private Point point1, point2; private String color; public Line() { super(); // TODO 自动生成的构造函数存根 } public Line(Point point1, Point point2, String color) { super(); this.point1 = point1; this.point2 = point2; this.color = color; } public Point getPoint1() { return point1; } public Point getPoint2() { return point2; } public String getColor() { return color; } public void setPoint1(Point point1) { this.point1 = point1; } public void setPoint2(Point point2) { this.point2 = point2; } public void setColor(String color) { this.color = color; } public double getDistance() { double linelength; linelength = Math.sqrt((point2.getY() - point1.getY()) * (point2.getY() - point1.getY()) + (point2.getX() - point1.getX()) * (point2.getX() - point1.getX())); return linelength; } public void display() { System.out.println("The line's color is:" + this.color); System.out.println("The line's begin point's Coordinate is:"); point1.display(); System.out.println("The line's end point's Coordinate is:"); point2.display(); System.out.println("The line's length is:" + String.format("%.2f", getDistance())); } } class Element { public Element() { super(); // TODO 自动生成的构造函数存根 } public void display() { } } class Plane extends Element { private String color; public Plane() { super(); // TODO 自动生成的构造函数存根 } public Plane(String color) { super(); this.color = color; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void display() { System.out.println("The Plane's color is:" + color); } }
这个题目要求设计一个父类由子类继承,在父类中有一个抽象方法,这抽象方法在子类中重写,就是由子类来实现这个方法。在java中的抽象方法就是以abstract修饰的方法,这种方法只声明返回的数据类型、方法名称和所需的参数,没有方法体,也就是说抽象方法只需要声明而不需要实现。
-
7-3 点线面问题再重构(容器类)
在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。
- 在原有类设计的基础上,增加一个GeometryObject容器类,其属性为
ArrayList<Element>
类型的对象(若不了解泛型,可以不使用<Element>
) - 增加该类的
add()
方法及remove(int index)
方法,其功能分别为向容器中增加对象及删除第index - 1
(ArrayList中index>=0)个对象 - 在主方法中,用户循环输入要进行的操作(choice∈[0,4]),其含义如下:
- 1:向容器中增加Point对象
- 2:向容器中增加Line对象
- 3:向容器中增加Plane对象
- 4:删除容器中第index - 1个数据,若index数据非法,则无视此操作
- 0:输入结束
choice = input.nextInt(); while(choice != 0) { switch(choice) { case 1://insert Point object into list ... break; case 2://insert Line object into list ... break; case 3://insert Plane object into list ... break; case 4://delete index - 1 object from list int index = input.nextInt(); ... } choice = input.nextInt(); } display()
方法进行输出。
类图如下所示:
- 以下情况为无效作业
- 无法运行
- 设计不符合所给类图要求
- 未通过任何测试点测试
- 判定为抄袭
输入格式:
switch(choice) { case 1://insert Point object into list 输入“点”对象的x,y值 break; case 2://insert Line object into list 输入“线”对象两个端点的x,y值 break; case 3://insert Plane object into list 输入“面”对象的颜色值 break; case 4://delete index - 1 object from list 输入要删除的对象位置(从1开始) ... }
输出格式:
- Point、Line、Plane的输出参考题目2
- 删除对象时,若输入的index超出合法范围,程序自动忽略该操作
输入样例:
在这里给出一组输入。例如:
1 3.4 5.6 2 4.4 8.0 0.98 23.888 Red 3 Black 1 9.8 7.5 3 Green 4 3 0
输出样例:
在这里给出相应的输出。例如:
(3.40,5.60) The line's color is:Red The line's begin point's Coordinate is: (4.40,8.00) The line's end point's Coordinate is: (0.98,23.89) The line's length is:16.25 (9.80,7.50) The Plane's color is:Green
code
import java.util.ArrayList; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); // TODO 自动生成的方法存根 int choice = input.nextInt(); double x1, y1, x2, y2; GeometryObject geometry = new GeometryObject(); while(choice != 0) { switch(choice) { case 1://insert Point object into list x1 = input.nextDouble(); y1 = input.nextDouble(); Point point = new Point(x1, y1); geometry.add(point); break; case 2://insert Line object into list String color; x1 = input.nextDouble(); y1 = input.nextDouble(); x2 = input.nextDouble(); y2 = input.nextDouble(); color = input.next(); if ((x1 < 0 || x1 > 200) || (y1 < 0 || y1 > 200) || (x2 < 0 || x2 > 200) || (y2 < 0 || y2 > 200)) { System.out.println("Wrong Format"); System.exit(0); } Point point1 = new Point(x1, y1); Point point2 = new Point(x2, y2); Line line = new Line(point1, point2, color); geometry.add(line); break; case 3://insert Plane object into list String color2; color2 = input.next(); Plane plane = new Plane(color2); geometry.add(plane); break; case 4://delete index - 1 object from list int index = input.nextInt(); geometry.remove(index-1); } choice = input.nextInt(); } for(Element element:geometry.getList()) { element.display(); } } } class Point extends Element { private double x, y; public Point() { super(); // TODO 自动生成的构造函数存根 } public Point(double x, double y) { super(); this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } public void setX(double x) { this.x = x; } public void setY(double y) { this.y = y; } public void display() { System.out.println("(" + String.format("%.2f", x) + "," + String.format("%.2f", y) + ")"); } } class Line extends Element { private Point point1, point2; private String color; public Line() { super(); // TODO 自动生成的构造函数存根 } public Line(Point point1, Point point2, String color) { super(); this.point1 = point1; this.point2 = point2; this.color = color; } public Point getPoint1() { return point1; } public Point getPoint2() { return point2; } public String getColor() { return color; } public void setPoint1(Point point1) { this.point1 = point1; } public void setPoint2(Point point2) { this.point2 = point2; } public void setColor(String color) { this.color = color; } public double getDistance() { double linelength; linelength = Math.sqrt((point2.getY() - point1.getY()) * (point2.getY() - point1.getY()) + (point2.getX() - point1.getX()) * (point2.getX() - point1.getX())); return linelength; } public void display() { System.out.println("The line's color is:" + this.color); System.out.println("The line's begin point's Coordinate is:"); point1.display(); System.out.println("The line's end point's Coordinate is:"); point2.display(); System.out.println("The line's length is:" + String.format("%.2f", getDistance())); } } class Element { public Element() { super(); // TODO 自动生成的构造函数存根 } public void display() { } } class Plane extends Element { private String color; public Plane() { super(); // TODO 自动生成的构造函数存根 } public Plane(String color) { super(); this.color = color; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public void display() { System.out.println("The Plane's color is:" + color); } } class GeometryObject{ private ArrayList<Element> list = new ArrayList<Element>(); public GeometryObject() { super(); // TODO 自动生成的构造函数存根 } public void add(Element element) { list.add(element); } public void remove(int index) { if(index>=0&&index<list.size()) list.remove(index); } public ArrayList<Element> getList() { return list; } }
在本题中使用了容器类GeometryObject
在这个类当中使用了ArrayList
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。有兴趣的可以点击这个链接了解Java ArrayList
SourceMonitor 生成报表内容 :
根据生成的报表内容我们可以看出函数的最大复杂度较高,而其他的都在正常范围内。
踩坑心得
-
题目集04
-
7-1 点线形系列1-计算两点之间的距离
问题1:对于输入字符串的合法性校验采用的方法并不合理
解决方案:应使用正则表达式来校验输入字符串的合法性,比如在本题中可以使用(String.matches("[1-5]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?)*"))
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。这个正则表达式的意思为字符串的第一个字符为数字1-5;后面是若干个点的坐标[+-]?
的意思为数字前面可能存在正负号。
-
7-2 点线形系列2-线的计算
问题1:计算交点出现问题
解决方案:更换计算交点的算法
更换后算法
public Point interline(Point p1, Point p2, Point p3) { Point sectionpoint = new Point(); double x0, y0; x0 = (p2.y * p3.x * p1.x - p3.y * p2.x * p1.x - p2.y * p3.x * x + p3.y * p2.x * x - y * p1.x * p3.x + p1.y * x * p3.x + y * p1.x * p2.x - p1.y * x * p2.x) / (p3.x * p1.y - p3.x * y - p2.x * p1.y + p2.x * y - p1.x * p3.y + p1.x * p2.y +x * p3.y - x * p2.y); y0 = (-p2.y * p3.x * p1.y + p3.y * p2.x * p1.y + p2.y * p3.x * y - p3.y * p2.x * y + y * p1.x * p3.y - y * p1.x * p2.y - x * p1.y * p3.y + p1.y * x * p2.y) / (p3.y * p1.x - p3.y * x - p2.y * p1.x + x * p2.y - p1.y * p3.x + p1.y * p2.x + y * p3.x - y * p2.x); sectionpoint.setX(x0); sectionpoint.setY(y0); return sectionpoint; }
-
7-3 点线形系列3-三角形的计算
问题1:三角形类型判断出错
解决方案:考虑到double类型数据可能的误差 ,对于判断两个数据是否相等不能直接采用==
的方法来判断,我们可以使用两个数据相减的绝对值与一个非常小的值来比较,比如判断直角的方法a*a+b*b==c*c
改为Math.abs(a*a+b*b-c*c)<0.000001
这样可以避免误差
问题2:分割后的面积计算出错
解决方案:分析出各种分析情况所对应的顶点,再根据海伦公式计算面积
-
双向链表练习
问题1:删除中间的某一个节点之后从后往前打印时分析并未删除
问题分析:从前往后打印时正确,但是从后往前打印时并未删除,应该是节点连接出现问题;
解决方案:画出示意图来进行节点连接
改进建议:
题目集04:
-
7-1 点线形系列1-计算两点之间的距离
将校验输入字符串合法性的方法改为使用正则表达式,之前所采用的方式利用循环两个一组判断可能出现的错误情况的方法并不合理,可能会出现误判或者未判
-
7-2 点线形系列2-线的计算
增加线类 以及合适的方法
-
7-3 点线形系列3-三角形的计算
对类的结构进行合理重构,可参考老师给出的类图:
总结:
经过这几周的java学习又了解到java的许多知识,比如java的三大特性1、封装,是指隐藏对象的属性和实现细节,仅对外提供公共访问方式;2、继承,从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力;3、多态,一个方法可以有多种实现版本,即“一种定义, 多种实现”,还学习到了正则表达式,Stream ,继承、多态、Java 重写(Override)与重载(Overload)等。其中影响最深的是关于泛型的知识:Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。在容器中用到了容器,而自己又不太了解在这个链接中我们可以了解一些关于泛型的知识:Java 泛型。在本次的期中考试当中主要是考察类图功能的实现和Java的简单语法,难度不高,但是提醒我们的是要根据类图一丝不苟的完成功能,不能添加减少,甚至不能更换类名,方法名,变量名等。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现