这是本学期第二次写blog,最近学到很多新的东西,我认为有必要总结一下学习成果。下面是我近期学习的内容和对题目集的理解,以及对测试点的踩坑心得。
首先呢是关于正则表达式的学习,所谓正则表达式,又称正规表示法、常规表示法,在代码中常简写为 regex、regexp 或 RE,它是计算机科学的一个概念。正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作,是一种可以用于模式匹配和替换的规范。一个正则表达式就是由普通的字符(如字符 a~z)以及特殊字符(元字符)组成的文字模式,它用以描述在查找文字主体时待匹配的一个或多个字符串。在String 类里也提供了几个特殊的方法。如boolean matches(String regex):判断该字符串是否匹配指定的正则表达式等。正则表达式是一种非常简单而且非常实用的工具。正则表达式是一个用于匹配字符串的模板。实际上,任意字符串都可以当成正则表达式使用。例如“abc”,它也是一个正则表达式,只是它只能匹配“abc”字符串。
下面是正则表达式的基本语法:
$ |
匹配一行的结尾。要匹配 $ 字符本身,请使用\$ |
^ |
匹配一行的开头。要匹配 ^ 字符本身,请使用\^ |
() |
标记子表达式的开始和结束位置。要匹配这些字符,请使用\(和\) |
[] |
用于确定中括号表达式的开始和结束位置。要匹配这些字符,请使用\[和\] |
{} |
用于标记前面子表达式的出现频度。要匹配这些字符,请使用\{和\} |
* |
指定前面子表达式可以出现零次或多次。要匹配 * 字符本身,请使用\* |
+ |
指定前面子表达式可以出现一次或多次。要匹配 + 字符本身,请使用\+ |
? |
指定前面子表达式可以出现零次或一次。要匹配 ?字符本身,请使用\? |
. |
匹配除换行符\n之外的任何单字符。要匹配.字符本身,请使用\. |
\ |
用于转义下一个字符,或指定八进制、十六进制字符。如果需匹配\字符,请用\\ |
| |
指定两项之间任选一项。如果要匹配丨字符本身,请使用\| |
. |
可以匹配任何字符 |
\d |
匹配 0~9 的所有数字 |
\D |
匹配非数字 |
\s |
匹配所有的空白字符,包括空格、制表符、回车符、换页符、换行符等 |
\S |
匹配所有的非空白字符 |
\w |
匹配所有的单词字符,包括 0~9 所有数字、26 个英文字母和下画线_ |
\W |
匹配所有的非单词字符 |
用户输入一组选项和数据,进行与四边形有关的计算。
以下四边形顶点的坐标要求按顺序依次输入,连续输入的两个顶点是相邻顶点,第一个和最后一个输入的顶点相邻。
选项包括:
1:输入四个点坐标,判断是否是四边形、平行四边形,判断结果输出true/false,结果之间以一个英文空格符分隔。
2:输入四个点坐标,判断是否是菱形、矩形、正方形,判断结果输出true/false,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
3:输入四个点坐标,判断是凹四边形(false)还是凸四边形(true),输出四边形周长、面积,结果之间以一个英文空格符分隔。 若四个点坐标无法构成四边形,输出"not a quadrilateral"
4:输入六个点坐标,前两个点构成一条直线,后四个点构成一个四边形或三角形,输出直线与四边形(也可能是三角形)相交的交点数量。如果交点有两个,再按面积从小到大输出四边形(或三角形)被直线分割成两部分的面积(不换行)。若直线与四边形或三角形的一条边线重合,输出"The line is coincide with one of the lines"。若后四个点不符合四边形或三角形的输入,输出"not a quadrilateral or triangle"。
后四个点构成三角形的情况:假设三角形一条边上两个端点分别是x、y,边线中间有一点z,另一顶点s:
1)符合要求的输入:顶点重复或者z与xy都相邻,如x x y s、x z y s、x y x s、s x y y。此时去除冗余点,保留一个x、一个y。
2) 不符合要求的输入:z 不与xy都相邻,如z x y s、x z s y、x s z y
5:输入五个点坐标,输出第一个是否在后四个点所构成的四边形(限定为凸四边形,不考虑凹四边形)或三角形(判定方法见选项4)的内部(若是四边形输出in the quadrilateral/outof the quadrilateral,若是三角形输出in the triangle/outof the triangle)。如果点在多边形的某条边上,输出"on the triangle或者on the quadrilateral"。若后四个点不符合四边形或三角形,输出"not a quadrilateral or triangle"。
基本格式:选项+":"+坐标x+","+坐标y+" "+坐标x+","+坐标y。点的x、y坐标之间以英文","分隔,点与点之间以一个英文空格分隔。
基本输出格式见每种选项的描述。
异常情况输出:
如果不符合基本格式,输出"Wrong Format"。
如果符合基本格式,但输入点的数量不符合要求,输出"wrong number of points"。
注意:输出的数据若小数点后超过3位,只保留小数点后3位,多余部分采用四舍五入规则进到最低位。小数点后若不足3位,按原始位数显示,不必补齐。例如:1/3的结果按格式输出为 0.333,1.0按格式输出为1.0
选项1、2、3中,若四边形四个点中有重合点,输出"points coincide"。
选项4中,若前两个输入线的点重合,输出"points coincide"。
这道题就需要用正则表达式来校验输入是否正确。这道题的格式错误有两种情况,第一种是输入的时候有除了数字、小数点、正负号之外的其他字符。这时应该显示Wrong Format
,还有一种情况是基本格式正确但是点的数量不对,比如说选项1中应该输入4个点,而我们输入了5个点,这时候就应该是wrong number of points 这种错误。输入的基本格式应该是这样的"[1-3]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?)*"),根据选项的不同可以在调节点的数量,比如选项1到3:
"[1-3]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?){4}",这样可以限制点数为4.
我们在搞定了输入之后就要开始考虑判断方式了,这里我选择列出一个四边形类,在四边形类中判断四边形的类型以及进行相关的计算。在判断四边形的时候我们可以这么判断,ABCD是一个四边形AB、AC、AD的斜率不相等并且AB和CD不能有交点。
在计算凹凸四边形的面积时,要将凹凸四边形分解成两个三角形进行判断。此外,在分解凹四边形时要注意有两种情况AC或BD做分界线,此时我们分别计算输出比较小的那一个即可。下面附上我的源代码。
import java.util.Scanner;
import java.text.DecimalFormat;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String str = input.nextLine();
String[] string;
String[] string1;
String[] string2;
Double[] a = new Double[100];
if (str.matches("[1-5]:[\\-\\+]?\\d+(\\.\\d+)?,[\\-\\+]?\\d+(\\.\\d+)?(\\s[\\-\\+]?\\d+(\\.\\d+)?,[\\-\\+]?\\d+(\\.\\d+)?){0,}\\s?")) {
if(str.matches("[1-3]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?)*")){
if (!str.matches("[1-3]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?){4}")) {
System.out.println("wrong number of points");
} else {
string = str.split(":|\\s|,");
string1 = str.split(":|\\s");
a[1] = Double.parseDouble(string[1]);
a[2] = Double.parseDouble(string[2]);
a[3] = Double.parseDouble(string[3]);
a[4] = Double.parseDouble(string[4]);
a[5] = Double.parseDouble(string[5]);
a[6] = Double.parseDouble(string[6]);
a[7] = Double.parseDouble(string[7]);
a[8] = Double.parseDouble(string[8]);
if (string[0].equals("1")) {
if (string1[1].equals(string1[2]) || string1[1].equals(string1[3]) || string1[1].equals(string1[4]) || string1[2].equals(string1[3]) || string1[2].equals(string1[4]) || string1[3].equals(string1[4])) {
System.out.print("points coincide");
} else {
Quadrilateral quadrilateral1 = new Quadrilateral(a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
System.out.print(quadrilateral1.Quadrilateral() + " ");
System.out.print(quadrilateral1.parallelogram());
}
} else if (string[0].equals("2")) {
Quadrilateral quadrilateral2 = new Quadrilateral(a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
if (quadrilateral2.Quadrilateral()) {
System.out.print(quadrilateral2.Lozenge() + " ");
System.out.print(quadrilateral2.Rectangle() + " ");
System.out.print(quadrilateral2.Square());
} else
System.out.print("not a quadrilateral\n");
} else if (string[0].equals("3")) {
Quadrilateral quadrilateral3 = new Quadrilateral(a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
if (quadrilateral3.Quadrilateral()) {
System.out.print(quadrilateral3.Bump());
System.out.printf(" ");
System.out.printf(new DecimalFormat("0.0##").format(quadrilateral3.Circumference()));
System.out.printf(" ");
System.out.printf(new DecimalFormat("0.0#####").format(quadrilateral3.Area()));
} else
System.out.print("not a quadrilateral\n");
}
}
}
if(str.matches("[4]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?)*")){
if (str.matches("[4]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?){6}")){
System.out.println("not a quadrilateral or triangle");
}else {
System.out.println("wrong number of points");
}
}
if(str.matches("[5]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?)*")) {
if (!str.matches("[5]:([+-]?\\d+(\\.\\d+)?,[+-]?\\d+(\\.\\d+)?\\s?){5}")) {
System.out.println("wrong number of points");
} else {
string = str.split(":|\\s|,");
string1 = str.split(":|\\s");
a[1] = Double.parseDouble(string[1]);
a[2] = Double.parseDouble(string[2]);
a[3] = Double.parseDouble(string[3]);
a[4] = Double.parseDouble(string[4]);
a[5] = Double.parseDouble(string[5]);
a[6] = Double.parseDouble(string[6]);
a[7] = Double.parseDouble(string[7]);
a[8] = Double.parseDouble(string[8]);
a[9] = Double.parseDouble(string[9]);
a[10] = Double.parseDouble(string[10]);
double x1 = a[1], y1 = a[2], x2 = a[3], y2 = a[4], x3 = a[5], y3 = a[6], x4 = a[7], y4 = a[8], x5 = a[9], y5 = a[10];
Quadrilateral quadrilateral = new Quadrilateral(x2, y2, x3, y3, x4, y4, x5, y5);
if(quadrilateral.Quadrilateral()) {
double whole = quadrilateral.Area();
double whole1 = Math.abs((x1 * y3 + x3 * y4 + x4 * y1 - x3 * y1 - x4 * y3 - x1 * y4) / 2.0D);
double whole2 = Math.abs((x2 * y1 + x1 * y5 + x5 * y2 - x1 * y2 - x5 * y1 - x2 * y5) / 2.0D);
double whole3 = Math.abs((x2 * y3 + x3 * y1 + x1 * y2 - x3 * y2 - x1 * y3 - x2 * y1) / 2.0D);
double whole4 = Math.abs((x4 * y1 + x1 * y5 + x5 * y4 - x1 * y4 - x5 * y1 - x4 * y5) / 2.0D);
if ((x1 - x2) * (y1 - y4) - (x1 - x4) * (y1 - y2) == 0 || (x1 - x4) * (y1 - y5) - (x1 - x5) * (y1 - y4) == 0 || (x1 - x2) * (y1 - y5) - (x1 - x5) * (y1 - y2) == 0) {
System.out.println("on the quadrilateral");
} else if (whole == whole1 + whole2 + whole3 + whole4) {
System.out.println("in the quadrilateral");
} else if (whole < whole1 + whole2 + whole3 + whole4) {
System.out.println("outof the quadrilateral");
}
}else if(x2==x3&&y2==y3||x2==x4&&y2==y4||x2==x5&&y2==y5){
Triangle triangle = new Triangle(x3,y3,x4,y4,x5,y5);
double whole = triangle.Area();
double whole1 = Math.abs((x1 * y4 + x4 * y5 + x5 * y1 - x4 * y1 - x5 * y4 - x1 * y5) / 2.0D);
double whole2 = Math.abs((x3 * y1 + x1 * y5 + x5 * y3 - x1 * y3 - x5 * y1 - x3 * y5) / 2.0D);
double whole3 = Math.abs((x3 * y4 + x4 * y1 + x1 * y3 - x4 * y3 - x1 * y4 - x3 * y1) / 2.0D);
if ((x1 - x3) * (y1 - y5) - (x1 - x5) * (y1 - y3) == 0 || (x1 - x5) * (y1 - y4) - (x1 - x4) * (y1 - y5) == 0 || (x1 - x3) * (y1 - y4) - (x1 - x4) * (y1 - y3) == 0) {
System.out.println("on the triangle");
} else if (whole == whole1 + whole2 + whole3) {
System.out.println("in the triangle");
} else if (whole < whole1 + whole2 + whole3) {
System.out.println("outof the triangle");
}
}else if(x3==x4&&y3==y4||x3==x5&&y3==y5){
Triangle triangle = new Triangle(x2,y2,x4,y4,x5,y5);
double whole = triangle.Area();
double whole1 = Math.abs((x1 * y4 + x4 * y5 + x5 * y1 - x4 * y1 - x5 * y4 - x1 * y5) / 2.0D);
double whole2 = Math.abs((x2 * y1 + x1 * y5 + x5 * y2 - x1 * y2 - x5 * y1 - x2 * y5) / 2.0D);
double whole3 = Math.abs((x2 * y4 + x4 * y1 + x1 * y2 - x4 * y2 - x1 * y4 - x2 * y1) / 2.0D);
if ((x1 - x2) * (y1 - y5) - (x1 - x5) * (y1 - y2) == 0 || (x1 - x5) * (y1 - y4) - (x1 - x4) * (y1 - y5) == 0 || (x1 - x2) * (y1 - y4) - (x1 - x4) * (y1 - y2) == 0) {
System.out.println("on the triangle");
} else if (whole == whole1 + whole2 + whole3) {
System.out.println("in the triangle");
} else if (whole < whole1 + whole2 + whole3) {
System.out.println("outof the triangle");
}
}else if(x4==x5&&y4==y5){
Triangle triangle = new Triangle(x2,y2,x3,y3,x5,y5);
double whole = triangle.Area();
double whole1 = Math.abs((x1 * y3 + x3 * y5 + x5 * y1 - x3 * y1 - x5 * y3 - x1 * y5) / 2.0D);
double whole2 = Math.abs((x2 * y1 + x1 * y5 + x5 * y2 - x1 * y2 - x5 * y1 - x2 * y5) / 2.0D);
double whole3 = Math.abs((x2 * y3 + x3 * y1 + x1 * y2 - x3 * y2 - x1 * y3 - x2 * y1) / 2.0D);
if ((x1 - x2) * (y1 - y5) - (x1 - x5) * (y1 - y2) == 0 || (x1 - x5) * (y1 - y3) - (x1 - x3) * (y1 - y5) == 0 || (x1 - x2) * (y1 - y3) - (x1 - x3) * (y1 - y2) == 0) {
System.out.println("on the triangle");
} else if (whole == whole1 + whole2 + whole3) {
System.out.println("in the triangle");
} else if (whole < whole1 + whole2 + whole3) {
System.out.println("outof the triangle");
}
}else {
System.out.println("not a quadrilateral or triangle");
}
}
}
} else
System.out.println("Wrong Format");
}
}
class Quadrilateral{
private double x1,y1;
public double x2,y2;
public double x3,y3;
public double x4,y4;
public Quadrilateral(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
this.x4 = x4;
this.y4 = y4;
}
public double Distance(double x1,double y1,double x2,double y2){
return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
public boolean Parallel(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4){
double k1=(y1-y2)/(x1-x2);
double k2=(y3-y4)/(x3-x4);
if(k1==k2||x1==x2&&x3==x4){
return true;
}else
return false;
}
public boolean Quadrilateral(){//判断是否为四边形
if(x1==x2&&x2==x3||x1==x3&&x3==x4||x2==x3&&x3==x4||x1==x2&&x2==x4){
return false;
}
double k1,k2,k3,k4,k5;
k1=(y1-y2)/(x1-x2);
k2=(y1-y3)/(x1-x3);
k3=(y1-y4)/(x1-x4);
k4=(y2-y3)/(x2-x3);
k5=(y2-y4)/(x2-x4);
double X=((x4-x3)*(x1*y2-x2*y1)-(x2-x1)*(x3*y4-x4*y3))/((y3-y4)*(x2-x1)-(y1-y2)*(x4-x3));
double Y=((y1-y2)*(x3*y4-x4*y3)-(y3-y4)*(x1*y2-x2*y1))/((y3-y4)*(x2-x1)-(y1-y2)*(x4-x3));
double distance1 = Distance(X,Y,x1,y1);
double distance2 = Distance(X,Y,x2,y2);
double distance3 = Distance(X,Y,x3,y3);
double distance4 = Distance(X,Y,x4,y4);
double distance5 = Distance(x1,y1,x2,y2);
double distance6 = Distance(x3,y3,x4,y4);
if(k1==k2||k1==k3||k2==k3||k4==k5||distance5==distance1+distance2&&distance6==distance3+distance4){
return false;
}else
return true;
}
public boolean parallelogram(){//判断平行四边形
if(Quadrilateral()&&Parallel(x1,y1,x2,y2,x3,y3,x4,y4)&&Distance(x1,y1,x2,y2)==Distance(x3,y3,x4,y4)){
return true;
}else
return false;
}
public boolean Lozenge(){//判断菱形
if(parallelogram()&&Distance(x1,y1,x2,y2)==Distance(x2,y2,x3,y3)){
return true;
}else
return false;
}
public boolean Rectangle(){//判断长方形
double k1=(y1-y2)/(x1-x2);
double k2=(y2-y3)/(x2-x3);
if(parallelogram()&&k1*k2==-1||x1==x2&&y2==y3){
return true;
}else
return false;
}
public boolean Square(){//判断正方形
if(Rectangle()&&Lozenge()){
return true;
}else
return false;
}
public double triangle_area(double x1,double y1,double x2,double y2,double x3,double y3){
double circumference = Distance(x1,y1,x2,y2)+Distance(x1,y1,x3,y3)+Distance(x3,y3,x2,y2);
double l=circumference/2;
return Math.sqrt(l*(l-Distance(x1,y1,x2,y2))*(l-Distance(x1,y1,x3,y3))*(l-Distance(x3,y3,x2,y2)));
}
public boolean Bump(){//判断凹凸性
double s1 = triangle_area(x1,y1,x2,y2,x3,y3);
double s2 = triangle_area(x3,y3,x4,y4,x1,y1);
double s3 = triangle_area(x2,y2,x3,y3,x4,y4);
double s4 = triangle_area(x4,y4,x1,y1,x2,y2);
double S = s1+s2;
double S1 = s3+s4;
if (S==S1){
return true;
}else
return false;
}
public double Circumference(){//四边形的周长
return Distance(x1,y1,x2,y2)+Distance(x2,y2,x3,y3)+Distance(x3,y3,x4,y4)+Distance(x1,y1,x4,y4);
}
public double Area() {//四边形的面积
if(Bump()) {
double s1 = triangle_area(x1, y1, x2, y2, x3, y3);
double s2 = triangle_area(x3, y3, x4, y4, x1, y1);
return s1 + s2;
}else {
if(triangle_area(x1, y1, x2, y2, x3, y3)+triangle_area(x3, y3, x4, y4, x1, y1)>triangle_area(x2, y2, x3, y3, x4, y4)+triangle_area(x4, y4, x1, y1, x2, y2)){
return triangle_area(x2, y2, x3, y3, x4, y4)+triangle_area(x4, y4, x1, y1, x2, y2);
}else
return triangle_area(x1, y1, x2, y2, x3, y3)+triangle_area(x3, y3, x4, y4, x1, y1);
}
}
}
class Triangle{
private double x1,y1;
public double x2,y2;
public double x3,y3;
public Triangle(double x1, double y1, double x2, double y2, double x3, double y3) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
}
public double Distance(double x1,double y1,double x2,double y2){
return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
public double Area(){
double circumference = Distance(x1,y1,x2,y2)+Distance(x1,y1,x3,y3)+Distance(x3,y3,x2,y2);
double l=circumference/2;
return Math.sqrt(l*(l-Distance(x1,y1,x2,y2))*(l-Distance(x1,y1,x3,y3))*(l-Distance(x3,y3,x2,y2)));
}
}
本题的类图如下:
本次代码仍然有待改进的地方,比如说选项4和5没有实现完全。在实现选项5时,未采用的是面积法而不是射线法。在判断平行四边形时有一种情况判断错误(斜率不存在且AB和CD有交点时)。
在近阶段的学习中,链表我学习的一个很实用的工具,链表与数组很相似,但是链表相较于数组,更容易实现数据的增加和删除。但是构建一个链表相对于数组要复杂很多,首先在链表之中,我们需要一个头指针和一个尾指针,所谓头指针,就是指向第一个节点的指针,尾指针是指向最后一个节点的指针。下面我先附上源码再解释各个函数的作用。
链表的类图如下:
interface LinearListInterface<E> {
public boolean isEmpty();
public int size();
public E get(int index);
public void remove();
public void remove(int index);
public void add(int index, E theElement);
public void add(E element);
public void printList();
public void printReverseList();
}
import java.util.Scanner;
import java.util.ArrayList;
public class LList<E> implements LinearListInterface<E>{
private Node<E> head,curr,tail;
private int size = 0;
public LList() {
super();
// TODO Auto-generated constructor stub
head = new Node<E>();
head.setNext(null);
head.setPrevious(null);
curr = tail = null;
this.size = 0;
}
@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return this.size == 0;
}
@Override
public int size() {
int i=0;
for (;head.getNext()!=null;head=head.getNext()){
i++;
}
return i;
}
@Override
public E get(int index) {
// TODO Auto-generated method stub
if(index < 1 || index > this.size) {
return null;
}
curr = head;
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 ;
}
curr = head;
if(index == 1) {
curr = head.getNext();
head.setNext(curr.getNext());
head.setPrevious(null);
}else if(index == this.size) {
for(int i = 1;i < index; i++) {
curr = curr.getNext();
}
tail = curr;
}else {
for(int i = 1;i < index; i++) {
curr = curr.getNext();
}
curr.setNext(curr.getNext().getNext());
curr.getNext().setPrevious(curr);
}
this.size --;
}
@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);
head.setPrevious(null);
tail = curr;
}else if(index == this.size + 1) {
curr.setPrevious(tail);
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(curr);
tempNode.setNext(curr);
curr.setPrevious(tempNode);
}
this.size ++;
}
public void remove(){
}
@Override
public void add(E element) {
// TODO Auto-generated method stub
this.add(this.size + 1,element);
}
@Override
public void printList() {
// 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("");
}
@Override
public void printReverseList() {//反向遍历链表
curr = head.getNext();
for(int i = 1; i < this.size;i ++) {
curr = curr.getNext();
}
for(int i = 1; i <= this.size;i ++) {
System.out.print(curr.getData() + " ");
curr = curr.getPrevious();
}
System.out.println("");
}
public E getFirst(){
if(this.size != 0) {
return head.getData();
}
return null;
}
public E getLast() {
if(this.size != 0) {
return tail.getData();
}
return null;
}
}
class E{
}
public class Node<E> {
private E data;
private Node<E> next;
private Node<E> previous;
public Node() {
}
public Node(E data, Node<E> next, Node<E> previous) {
this.data = data;
this.next = next;
this.previous = previous;
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> next) {
this.next = next;
}
public Node<E> getPrevious() {
return previous;
}
public void setPrevious(Node<E> previous) {
this.previous = previous;
}
}
public class Main {
public static void main(String[] args){
LList<Integer> list = new LList();
list.add(2);
list.add(4);
list.add(6);
list.add(8);
list.printList();
list.printReverseList();//反向遍历链表
list.remove(4);
list.printList();
list.remove(2);
list.printReverseList();//反向遍历链表
list.add(2, 100);
list.printList();
list.add(10);
System.out.println(list.get(4));
System.out.println(list.size());
}
}
这是一个双向链表,双向链表和单向链表最大的不同是双向链表中每一个节点中都有一个previous 指针,这个指针保存的是前一个节点的内存地址。
Add 函数:这是链表中增加节点的函数,这个函数的基本思路是:(比如要增加一个4节点)首先找到需要添加的位置,并找到前一个节点(第三个节点),将第三个节点中的next存储新的节点的内存地址,再将新的节点中的next存储原来第四个节点的内存地址,这样就成功插入了一个新的节点。需要注意的是,如果我们要插入一个头节点,那么我们需要将新的头节点的next存储原来头节点的内存地址,还需要将头指针指向了新的头节点。
Remove 函数:这是链表中删除节点的函数,这个函数的基本思路是:(比如要删除第四个节点)首先找到第三个节点的位置,将第三个节点中的next存储第五个节点的内存地址,这样就成功删除了第四个节点。需要注意的是当我们要删除头节点是,只需要将头指针指向第二个节点即可,当我们要删除尾节点是,上述的方法就会有问题,(假设一共有8个节点),删除第八个节点是,需要找到第7个节点的位置,当我们使用
curr.setNext(curr.getNext().getNext());
这个语句来操作是,运行阶段就会出现问题,因为没有第九个节点,所以在删除第八个节点时,只需要找到第七个节点并把第七个节点中的next设置为null即可。
Printlist函数是一个输出链表节点中国属性的函数,在这个函数中,我们需要遍历一遍链表,采用for或foreach循环均可,目的就是将链表从头到尾遍历。
这是链表的运行结果:
值得一提的是,上述的链表中使用了泛型和接口。这两个东西我的理解不是很到位,读者需要自己搜索理解一下。
下面分析一下期中考试的三道题目:
设计一个类表示平面直角坐标系上的点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:长度值
类图如下:
本题比较简单,直接附上源码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Double x1=input.nextDouble();
Double y1=input.nextDouble();
Double x2=input.nextDouble();
Double y2=input.nextDouble();
String string = input.next();
if(x1>0&&x1<=200&&y1>0&&y1<=200&&x2>0&&x2<=200&&y2>0&&y2<=200) {
Point point1 = new Point(x1, y1);
Point point2 = new Point(x2, y2);
Line line = new Line(point1, point2, string);
line.display();
}else
System.out.println("Wrong Format");
}
}
class Point{
private double x;
private double y;
public Point() {
}
public Point(double x, double y) {
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 void display(){
System.out.printf("(%.2f,%.2f)",x,y);
}
}
class Line{
private Point point1;
private Point point2;
private String color;
public Line() {
}
public Line(Point point1, Point point2, String color) {
this.point1 = point1;
this.point2 = point2;
this.color = color;
}
public Point getPoint1() {
return point1;
}
public void setPoint1(Point point1) {
this.point1 = point1;
}
public Point getPoint2() {
return point2;
}
public void setPoint2(Point point2) {
this.point2 = point2;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getDistance(){
return Math.sqrt((point1.getX()-point2.getX())*(point1.getX()-point2.getX())+(point1.getY()-point2.getY())*(point1.getY()-point2.getY()));
}
public void display(){
System.out.println("The line's color is:"+color);
System.out.println("The line's begin point's Coordinate is:");
point1.display();
System.out.println();
System.out.println("The line's end point's Coordinate is:");
point2.display();
System.out.println();
System.out.printf("The line's length is:%.2f",this.getDistance());
}
}
第二题:
在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。
element = p1;//起点Point
element.display();
element = p2;//终点Point
element.display();
element = line;//线段
element.display();
element = plane;//面
element.display();
输出格式如下:
(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:颜色值
类图如下:
这道题相较于第一题使用了继承和多态,这两个特性可以使得代码的耦合度变得更低,代码如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Double x1=input.nextDouble();
Double y1=input.nextDouble();
Double x2=input.nextDouble();
Double y2=input.nextDouble();
String string = input.next();
Element element = new Element() {
@Override
public void display() {
}
};
if(x1>0&&x1<=200&&y1>0&&y1<=200&&x2>0&&x2<=200&&y2>0&&y2<=200) {
Point point1 = new Point(x1, y1);
Point point2 = new Point(x2, y2);
Line line = new Line(point1, point2, string);
Plane plane = new Plane(string);
element = point1;
element.display();
element = point2;
element.display();
element = line;
element.display();
element = plane;
element.display();
}else
System.out.println("Wrong Format");
}
}
class Point extends Element{
private double x;
private double y;
public Point() {
}
public Point(double x, double y) {
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 void display(){
System.out.printf("(%.2f,%.2f)\n",x,y);
}
}
class Line extends Element{
private Point point1;
private Point point2;
private String color;
public Line() {
}
public Line(Point point1, Point point2, String color) {
this.point1 = point1;
this.point2 = point2;
this.color = color;
}
public Point getPoint1() {
return point1;
}
public void setPoint1(Point point1) {
this.point1 = point1;
}
public Point getPoint2() {
return point2;
}
public void setPoint2(Point point2) {
this.point2 = point2;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getDistance(){
return Math.sqrt((point1.getX()-point2.getX())*(point1.getX()-point2.getX())+(point1.getY()-point2.getY())*(point1.getY()-point2.getY()));
}
public void display(){
System.out.println("The line's color is:"+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.printf("The line's length is:%.2f\n",this.getDistance());
}
}
class Plane extends Element{
private String color;
public void display(){
System.out.println("The Plane's color is:"+color);
}
public Plane(String color) {
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
abstract class Element{
public abstract void display();
public Element() {
}
}
第三题:
在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。
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();
}
本题使用了容器,代码如下:
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
ArrayList<Element> arrayList = new ArrayList<>();
Scanner input = new Scanner(System.in);
GeometryObject geometryObject = new GeometryObject();
Element element = new Element() {
@Override
public void display() {
}
};
int choice = 0;
while(choice != 0) {
choice= input.nextInt();
switch(choice) {
case 1://insert Point object into list
Point point = new Point(input.nextDouble(), input.nextDouble());
element = point;
geometryObject.add(element);
break;
case 2://insert Line object into list
Point point1 = new Point(input.nextDouble(), input.nextDouble());
Point point2 = new Point(input.nextDouble(), input.nextDouble());
Line line = new Line(point1, point2, string);
element = line;
geometryObject.add(element);
break;
case 3://insert Plane object into list
Plane plane = new Plane(string);
element = plane;
geometryObject.add(element);
break;
case 4://delete index - 1 object from list
int index = input.nextInt();
geometryObject.remove(index);
}
}
arrayList = geometryObject.getArrayList();
for (int i = 0; i < arrayList.size(); i++) {
arrayList.get(i).display();
}
}
}
class Point extends Element{
private double x;
private double y;
public Point() {
}
public Point(double x, double y) {
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 void display(){
System.out.printf("(%.2f,%.2f)\n",x,y);
}
}
class Line extends Element{
private Point point1;
private Point point2;
private String color;
public Line() {
}
public Line(Point point1, Point point2, String color) {
this.point1 = point1;
this.point2 = point2;
this.color = color;
}
public Point getPoint1() {
return point1;
}
public void setPoint1(Point point1) {
this.point1 = point1;
}
public Point getPoint2() {
return point2;
}
public void setPoint2(Point point2) {
this.point2 = point2;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getDistance(){
return Math.sqrt((point1.getX()-point2.getX())*(point1.getX()-point2.getX())+(point1.getY()-point2.getY())*(point1.getY()-point2.getY()));
}
public void display(){
System.out.println("The line's color is:"+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.printf("The line's length is:%.2f\n",this.getDistance());
}
}
class Plane extends Element{
private String color;
public void display(){
System.out.println("The Plane's color is:"+color);
}
public Plane(String color) {
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
abstract class Element{
public abstract void display();
public Element() {
}
}
class GeometryObject{
ArrayList<Element> arrayList = new ArrayList<>();
public void add(Element element){
arrayList.add(element);
}
public void remove(int index){
arrayList.remove(index-1);
}
public ArrayList<Element> getArrayList() {
return arrayList;
}
public GeometryObject(ArrayList<Element> arrayList) {
this.arrayList = arrayList;
}
public GeometryObject() {
}
}
第一次写这个程序是,我对于容器和泛型的概念不太了解导致没有写出这道题,后面进行修改之后可以正在运行,上述源代码即是修改之后的。
总结一下近期Java的学习成果,首先是对于正则表达式,泛型,容器的学习,以及对多态和继承的进一步强化训练,在写pta习题集时,我学会了先分析题目在动笔去写,这样既可以保证代码的思路明确也能提高准确率,对于后期的修改也是大有裨益。同时在写pta时我也发现了,我有很多的方法用的都不得当,比如凸四边形的计算中的计算交点个数,使用射线法会较为简单,而我使用的面积法就十分冗杂且准确率很低。这就说明了我不仅要学习Java的基本知识点,还应该学习一些常用的算法。
最近疫情形势还是不容乐观,在宿舍上网课的学习效率仍不够高,希望疫情早日结束。