对之前发布的PTA题目集、超星作业以及期中考试的总结性Blog
一、前言
我将在这篇博客中分析PTA题目集4和Java实现链表还有期中考试的题目。其中题目集4是关于图形设计的递增式题目集,每一题的做答都关系到之后的题目,所以在实现代码的时候需要先思考代码中的结构,要同时考虑三个题目之间的联系,再考虑应该用哪种结构最适合,不然就会像我一样,在做第一题时发现很简单,结果到后面的题目发现之前的代码就没有几个能用的,到最后还是重新写了第一题。而Java实现链表则是考验我们对接口的熟练度,还有就C语言链表学的好不好,其实到现在我还是没有搞懂。最后期中的题目是考验我们类之间的关系是否能够理顺,还与父类和子类之间的继承关系有一定联系。接下来我会按照顺序分析与解答我在这几次练习中学到的东西并分享给你们。
二、题目
(1)PTA题目集4(因为我觉得只有第三个题目最有代表性所以我只分析这个)
  
  
其实说白了这种题目就是考我们写方法的能力,因为在这个题目中我们只需要一个类,一个其中的属性是x1,y1,x2......的类。因为在这个题目中能进行判断的只有坐标上的点,这意味者我们只能通过这几个坐标来实现上面题目中的判断像什么锐角三角形,钝角三角形之类的。所以基础已经打好了,但不要忘了数据封装,这很重要。
class GetPoint{//得到直线与三角形的交点个数
	double x1;
	double y1;
	double x2;
	double y2;
	double x3;
	double y3;
	double x4;
	double y4;
	double x5;
	double y5;
	public GetPoint() {
	}
	public GetPoint(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4,double x5,double y5) {
		this.x1 = x1;
		this.y1 = y1;
		this.x2 = x2;
		this.y2 = y2;
		this.x3 = x3;
		this.y3 = y3;
		this.x2 = x4;
		this.y2 = y4;
		this.x3 = x5;
		this.y3 = y5;
	}
}
我好像忘记说如何把输入的坐标格式提取成x1,x2.....了,但是没有关系,我们只需要再创个只有字符的类。(上面好像也少了private)
class CheckNumber{
	private String s;
	public CheckNumber() {
		
	}
	public CheckNumber(String s) {
		this.s = s;
	}
}
那么接下来就是写方法的时候,我举几个例子。

public boolean getTrue4(double x1,double y1,double x2) {//判断是否为钝角
		double a = x1;
		double b = y1;
		double c = x2;
		boolean getTrue;
		getTrue = (a*a>b*b+c*c||b*b>a*a+c*c||c*c>a*a+b*b);
		return getTrue;
	}
	public boolean getTrue5(double x1,double y1,double x2) {//判断是否为直角
		double a = x1;
		double b = y1;
		double c = x2;
		boolean getTrue;
		getTrue = (a*a==b*b+c*c||b*b==a*a+c*c||c*c==a*a+b*b);
		return getTrue;
	}
	public boolean getTrue6(double x1,double y1,double x2) {//判断是否为锐角
		double a = x1;
		double b = y1;
		double c = x2;
		boolean getTrue;
		getTrue = (a*a<b*b+c*c&&b*b<a*a+c*c&&c*c<a*a+b*b);
		return getTrue;
	}
这里是我来分别判断锐角、直角、钝角三角形的方法,其实很简单,就是运用三角形的定义然后再通过代码的知识表达出来。
再是这个:
  
public String getArea(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4,double x5,double y5) {//通过叉乘的是否同号判断交点的个数
		double t = 0;//只有两个交点时才能判断面积
		double l1 = (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1);//得到叉乘的值
		double l2 = (x2-x1)*(y4-y1)-(y2-y1)*(x4-x1);
		double l3 = (x2-x1)*(y5-y1)-(y2-y1)*(x5-x1);
		double s = 0,s1 = 0,s2 = 0,s3 = 0;
		
		double k1 = ((y1-y2)/(x1-x2));//ab
		double k2 = ((y3-y4)/(x3-x4));//AB
		double k3 = ((y3-y5)/(x3-x5));//AC
		double k4 = ((y4-y5)/(x4-x5));//BC
		double b1 = y1-k1*x1;//ab
		double b2 = y3-k2*x3;//AB
		double b3 = y3-k3*x3;//AC
		double b4 = y4-k4*x4;//BC
		
		double m1 = ((b2-b1)/(k1-k2));
		double n1 = k1*m1+b1;//ab与AB
		double m2 = ((b3-b1)/(k1-k3));
		double n2 = k1*m2+b1;//ab与AC
		double m3 = ((b4-b1)/(k1-k4));
		double n3 = k1*m3+b1;//ab与BC
		s = Math.abs((x4-x3)*(y5-y3)-(y4-y3)*(x5-x3));
		s = s/2;
		s1 = Math.abs((x3-x4)*(n3-y4)-(y3-y4)*(m3-x4));//A
		s1 = s1/2;
		s2 = Math.abs((x4-x3)*(n2-y3)-(y4-y3)*(m2-x3));//B
		s2 = s2/2;
		s3 = Math.abs((x5-x3)*(n1-y3)-(y5-y3)*(m1-x3));//C
		s3 = s3/2;
		if(l1==0) {
			if(s1>s/2) {
				t = s-s1;
			}
			else if(s1==s/2) {
				t = s1;
			}
			else {
				t = s1;
			}
		}
		else if(l2==0) {
			if(s2>s/2) {
				t = s-s2;
			}
			else if(s2==s/2) {
				t = s2;
			}
			else {
				t = s2;
			}
		}
		else if(l3==0) {
			if(s3>s/2) {
				t = s-s3;
			}
			else if(s3==s/2) {
				t = s3;
			}
			else {
				t = s3;
			}
		}
        
		double t1 = s-t;
		return t+" "+t1;
	}
我在这个地方运用了一点数学知识,我通过求各个点之间的叉乘来得到被直线分割的两个三角形的面积,因为三角形的两个边可以看作两个向量,而它们的叉乘就是这个三角形面积的两倍,当然这样的方法也有困难的地方,就是要在草稿纸上先写出表达式,如果有什么地方写错的话就很难测试出来,我想最难的还是打草稿吧,因为很少有人写代码之前先在纸上写过程。
(2)java实现链表

这个是我们老师自己布置给我们做的,没错他只讲了一点(相当于什么都没有讲),然后就叫我们写这个。怎么说呢,老师太高看我们了,我们不是生来就是很会写代码的,我连上面的的方法我都写不全,你让我写个链表,我能怎么办。但最后老师还是给我们展示了如何写一个链表,那就让我复述一下吧。首先,是接口的问题:
public interface LinearListInterface<E> {
    public boolean isEmpty();//检查链表是否为空
    public int size();//求链表的长度
    public E get(int index);//查询下标为index的节点的值
    public void remove(int index);//删除下标为index的节点
    public void add(int index, E theElement);//在第index后添加值
    public void add(E element);//在链表末尾添加值
    public void printList();//输出链表    
}
这里是链表中所要拥有的方法。
public class Node<E> {
	private E o;
	private Node<E> next;
	
	public E getO() {
		return o;
	}
	public void setO(E o) {
		this.o = o;
	}
	public Node<E> getNext() {
		return next;
	}
	public void setNext(Node<E> next) {
		this.next = next;
	}
}
这是运用了范型的结点类。
public class LList<E> implements LinearListInterface<E>{
	
	private Node<E> head = null, curr = null, tail = null;
	private int size = 0; 
	public LList() {
		// TODO 自动生成的构造函数存根
	}
	
	public int getSize() {
		return size;
	}
}
这是继承接口的链表类,其中的方法我没有全部截出来,我来解释一下。其实和c语言时期的链表相同,都是有头有尾的,当头为null时这个链表是为空的,当头不为空时就可以进行下一步,其中最重要的还有next这个是实现链表重要一步,接下来一个方法的实现为这个。
//在第index后添加值
	public void add(int index, E theElement) {
		if(this.get(index) == null) 
			System.out.println("Not Found!");
		else if(index == this.size) {
			add(theElement);
		}
		else {
			int num = 0;
			Node<E> p = this.head;
			Node<E> temp = null;
			while(p != null && num != index-1) {
				num++;
				temp = p;
				p = p.getNext();
			}
			curr = new Node<E>();
			curr.setO(theElement);
			curr.setNext(p.getNext());
			p.setNext(curr);
			this.size++;
			System.out.println("OK!");
		}
	}
(3)期中考试题目

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner input = new Scanner(System.in);
		double a1 =input.nextDouble();
		double a2 =input.nextDouble();
		double a3 =input.nextDouble();
		double a4 =input.nextDouble();
		String a5 = input.next();
		Point point1 = new Point();
		Point point2 = new Point();
		Line line = new Line();
		if(a1>200||a2>200||a3>200||a4>200) {
			System.out.println("Wrong Format");
		}
        else if(a1<0||a2<0||a3<0||a4<0){
            System.out.println("Wrong Format");
        }
		else {
			point1.setX(a1);
			point1.setY(a2);
			point2.setX(a3);
			point2.setY(a4);
			line.setPoint1(point1);
			line.setPoint2(point2);
			line.setColor(a5);
			line.display();
		}
	}
}
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.println("("+String.format("%.2f", x)+","+String.format("%.2f", 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 this.color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public double getDistance() {
		double x1 = point1.getX();
		double y1 = point1.getY();
		double x2 = point2.getX();
		double y2 = point2.getY();
		double l = Math.sqrt(Math.pow((x1-x2),2)+Math.pow((y1-y2),2));
		return l;
	}
	public void display() {
		System.out.println("The line's color is:"+getColor());
		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()));
	}
}
第一题很简单,就是除了main类以外还有两个类,line和point类其中line类中的私有属性为point类,所以在line类中可以掉用point类中的方法。

第二题就增加了一个父类和一个plane类,其中父类为element类是个抽象类,只有一个抽象方法。
bstract class Element{
		public  void display() 
	}
}
class Plane extends Element {
	private String color;	
	public Plane() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Plane(String color) {
		super();
		this.color = color;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	@Override
	public void display() {
		// TODO Auto-generated method stub
		System.out.println("The Plane's color is:" + this.color);
	}
}
第三题:

在这题中最要的是main类的写法和geometryobject的写法,因为在这个类中涉及到了remove的方法。其中还创建了链表,把element作为对象放入其中这样就可以更加简便的对数据进行删除。(我没有做出这题来所以也不是很清楚)
class GeometryObject{
	private ArrayList<Element> list = new ArrayList<>();
	public GeometryObject() {
	}
	public void add(Element element) {
		list.add(element);
	}
	public void remove(int index) {
		if(index < 1 || index > list.size()) {
			return;
		}		
		list.remove(index - 1);
	}
	public ArrayList<Element> getList(){
		return this.list;
	}
}
public class Main {
	public static void main(String[] args) {
		double x1,y1,x2,y2;
		String color;
		Scanner input = new Scanner(System.in);
		int choice = 0,index = 0;
		
		GeometryObject container = new GeometryObject();		
		
		choice = input.nextInt();
		while(choice != 0) {
			switch(choice) {
			case 1:
				x1 = input.nextDouble();
				y1 = input.nextDouble();
				container.add(new Point(x1,y1));
				break;
			case 2:
				x1 = input.nextDouble();
				y1 = input.nextDouble();
				x2 = input.nextDouble();
				y2 = input.nextDouble();
				color = input.next();
				container.add(new Line(new Point(x1,y1),new Point(x2,y2),color));
				break;
			case 3:
				color = input.next();
				container.add(new Plane(color));
				break;
			case 4:
				index = input.nextInt();
				container.remove(index);
				break;
			}
			choice = input.nextInt();
		}
		
		for(Element element:container.getList()) {
			element.display();
		}
	}
}
三、踩坑心得
我踩的坑太多了,就比如PTA题目集4的那几题。我其实创建了好几个类,每个选项拥有一个类,太奢饰了。而且在那些类中我都没有设置私有变量,没报错真是太侥幸了。还有就是期中题目集我被题目所描述的坑了,我在结束后一看,我发现是我的main类写错了,悔不当初。
四、改进建议
我的题目集4可以改成这样:
public class Main {
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Scanner input = new Scanner(System.in);
		String s= input.nextLine();
		String [] str = new String [10];
		int choice = (int)s.charAt(0) - '0';
		
		if(s.length() <= 2)
		{
			System.out.println("Wrong Format");
		    System.exit(0);
		}
		if(s.charAt(1) != ':')
		{
			System.out.println("Wrong Format");
		    System.exit(0);
		}
		if(CheckCharcter(s,' ') == 0)
		{
			if(CheckDate(s.substring(2))) 
			{
				System.out.println("wrong number of points");
			    System.exit(0);
			}
			else
			{
				System.out.println("Wrong Format");
			    System.exit(0);
			}
		}
		
		int space = s.indexOf(' ');
		str[1] = s.substring(2,s.indexOf(' '));
		if(!CheckDate(str[1]))
		{
			System.out.println("Wrong Format");
		    System.exit(0);
		}
		for(int i=2;i<=CheckCharcter(s,' ');i++)
		{
			str[i] = s.substring(space+1,s.indexOf(' ',space+1));
			if(!CheckDate(str[i]))
			{
				System.out.println("Wrong Format");
			    System.exit(0);
			}
			space = s.indexOf(' ',space+1);
		}
		str[CheckCharcter(s,' ')+1] = s.substring(space+1);
		if(!CheckDate(str[CheckCharcter(s,' ')+1]))
		{
			System.out.println("Wrong Format");
		    System.exit(0);
		}
}
这样我就不用再大费周折去写哪个字符串类。
五、总结
在这三周我总算是入门一点了,不会再是像之前一样不知道应该干什么。我自我总结一下,就是对类之间的关系更加清楚了一点,还有父类的继承和接口的使用,当然我有很多需要学习的,只希望接下来的路会更轻松一点吧。

                
            
        
浙公网安备 33010602011771号