Programming Assignment 3: Collinear Points
Coursera:Programming Assignment 3: Pattern Recognition
The problem. Given a set of N distinct points in the plane, draw every (maximal) line segment that connects a subset of 4 or more of the points.

问题是给出N个不同的点,找出并画出4个以上给出的点连接成的直线。
问题要求用Brute force直接遍历找出4个点连成的直线,再用应用排序算法的Fast算法找出4个以上的点连成的直线。
作为开始,给出Point类的代码。
import java.util.Comparator; public class Point implements Comparable<Point> { //实现comparabor接口使用slope作为键值进行比较 private final class SlopeOrder implements Comparator<Point> { public int compare(Point v, Point w) { if (Point.this.slopeTo(v) > Point.this.slopeTo(w)) return 1; else if (Point.this.slopeTo(v) < Point.this.slopeTo(w)) return -1; else return 0; } } // compare points by slope public final Comparator<Point> SLOPE_ORDER = new SlopeOrder(); private final int x; // x coordinate private final int y; // y coordinate // create the point (x, y) public Point(int x, int y) { /* DO NOT MODIFY */ this.x = x; this.y = y; } // plot this point to standard drawing public void draw() { /* DO NOT MODIFY */ StdDraw.point(x, y); } // draw line between this point and that point to standard drawing public void drawTo(Point that) { /* DO NOT MODIFY */ StdDraw.line(this.x, this.y, that.x, that.y); } // slope between this point and that point public double slopeTo(Point that) { double slope; if (this.x == that.x && this.y == that.y) slope = Double.NEGATIVE_INFINITY; else if (this.x == that.x) slope = Double.POSITIVE_INFINITY; else if (this.y == that.y) slope = 0; else slope = ((double)(this.y - that.y)) / (this.x - that.x); return slope; } // is this point lexicographically smaller than that one? // comparing y-coordinates and breaking ties by x-coordinates public int compareTo(Point that) { if (this.y > that.y || (this.y == that.y && this.x > that.x)) return 1; else if (this.y < that.y || (this.y == that.y && this.x < that.x)) return -1; else return 0; } // return string representation of this point public String toString() { /* DO NOT MODIFY */ return "(" + x + ", " + y + ")"; } // unit test public static void main(String[] args) { /* YOUR CODE HERE */ } }
Point类按照问题要求实现。其中实现Comparator接口的内部类可以使排序算法以不同的键值进行排序。
首先Point类需声明一个SlopeOrder的共有实例变量SLOPE_ORDER,并在实现Comparator的内部类中实现compare方法,这样排序算法只要将第二个参数接收Comparator的对象,在方法中排序时调用该对象的compare方法即可按对象对应键值进行排序。Point类实现了SlopeOrder内部类,这样Fast方法可以利用调用的点this与其他两个点v,w的对应斜率进行排序,系统排序算法有接收comparator对象的对应排序算法,所以调用Arrays.sort即可,这样可以将Brute force方法的运行时间级N^4提高到Fast方法的N^2logN。
下面是Fast类的关键代码
LinkedList<Point> pointList = new LinkedList<Point>(); for (int i = 0; i < N; i++) { //每次slope排序会将i当前对应的点排在第一,所以只需比较points[0]与points中 //其他元素所成斜率是否相等 Arrays.sort(points); Arrays.sort(points, points[i].SLOPE_ORDER); //以slope作为键值进行排序 for (int j = 0; j < N-1; j++) { pointList.add(points[j]); while (j+1 < N && points[0].slopeTo(points[j]) == points[0].slopeTo(points[j+1])) { pointList.add(points[++j]); } //只输出按compareTo排序的点,所以顺序不用但处于同一直线个数相同的只输出一次 if (pointList.size() >= 3 && points[0].compareTo(pointList.get(0)) < 0) { StdOut.print(points[0].toString()); for (int k = 0; k < pointList.size(); k++) StdOut.print(" -> " + pointList.get(k).toString()); StdOut.println(); points[0].drawTo(pointList.get(pointList.size() - 1)); } pointList.clear(); } }

浙公网安备 33010602011771号