import java.util.Comparator;
import edu.princeton.cs.algs4.StdDraw;
public classPointimplementsComparable<Point> {privatefinal int x; // x-coordinate of this pointprivatefinal int y; // y-coordinate of this point/**
* Initializes a new point.
*
* @param x the <em>x</em>-coordinate of the point
* @param y the <em>y</em>-coordinate of the point
*/
public Point(int x, int y) {
/* DO NOT MODIFY */this.x = x;
this.y = y;
}
/**
* Draws this point to standard draw.
*/
public void draw() {
/* DO NOT MODIFY */
StdDraw.point(x, y);
}
/**
* Draws the line segment between this point and the specified point
* to standard draw.
*
* @param that the other point
*/
public void drawTo(Point that) {
/* DO NOT MODIFY */
StdDraw.line(this.x, this.y, that.x, that.y);
}
/**
* Returns the slope between this point and the specified point.
* Formally, if the two points are (x0, y0) and (x1, y1), then the slope
* is (y1 - y0) / (x1 - x0). For completeness, the slope is defined to be
* +0.0 if the line segment connecting the two points is horizontal;
* Double.POSITIVE_INFINITY if the line segment is vertical;
* and Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal.
*
* @param that the other point
* @return the slope between this point and the specified point
*/
public double slopeTo(Point that) {
if ((this.x == that.x) && (this.y == that.y)) {
return Double.NEGATIVE_INFINITY;
} elseif (this.x == that.x) {
return Double.POSITIVE_INFINITY;
} elseif (this.y == that.y) {
return0;
} else {
return (that.y - this.y) / (double) (that.x - this.x);
}
}
/**
* Compares two points by y-coordinate, breaking ties by x-coordinate.
* Formally, the invoking point (x0, y0) is less than the argument point
* (x1, y1) if and only if either y0 < y1 or if y0 = y1 and x0 < x1.
*
* @param that the other point
* @return the value <tt>0</tt> if this point is equal to the argument
* point (x0 = x1 and y0 = y1);
* a negative integer if this point is less than the argument
* point; and a positive integer if this point is greater than the
* argument point
*/
public int compareTo(Point that) {
if ((this.x == that.x) && (this.y == that.y)) {
return0;
} elseif ((that.y > this.y) ||
((that.y == this.y) && (that.x > this.x))) {
return -1;
} else {
return1;
}
}
/**
* Compares two points by the slope they make with this point.
* The slope is defined as in the slopeTo() method.
*
* @return the Comparator that defines this ordering on points
*/
public Comparator<Point> slopeOrder() {
returnnew SlopeOrder(this);
}
privateclassSlopeOrderimplementsComparator<Point> {private Point p0;
public SlopeOrder(Point invokePoint) {
p0 = invokePoint;
}
public int compare(Point p1, Point p2) {
double d01 = p0.slopeTo(p1);
double d02 = p0.slopeTo(p2);
if (d01 < d02) {
return -1;
} elseif (d01 > d02) {
return1;
} else {
return0;
}
}
}
/**
* Returns a string representation of this point.
* This method is provide for debugging;
* your program should not rely on the format of the string representation.
*
* @return a string representation of this point
*/
public String toString() {
/* DO NOT MODIFY */return"(" + x + ", " + y + ")";
}
/**
* Unit tests the Point data type.
*/
public static void main(String[] args) {
}
}
FastCollinearPoints
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;
import java.util.Arrays;
publicclass FastCollinearPoints {
privateint lineNumber;
private Node last;
publicFastCollinearPoints(Point[] points) // finds all line segments containing 4 or more points
{
if (points == null) {
thrownew IllegalArgumentException();
}
lineNumber = 0;
int num = points.length;
Point[] clone = new Point[num];
for (int i = 0; i < num; i++) {
if (points[i] == null) {
thrownew IllegalArgumentException();
}
for (int j = i + 1; j < num; j++) {
if (points[i].compareTo(points[j]) == 0) {
thrownew IllegalArgumentException();
}
}
clone[i] = points[i];
}
Arrays.sort(clone);
if (num < 4) {
return;
}
for (int i = 0; i < num - 1; i++) {
int tempPointsNum = 0;
Point[] tempPoints = new Point[num - 1];
for (int j = 0; j < num; j++) {
if (i != j) tempPoints[tempPointsNum++] = clone[j];
}
Arrays.sort(tempPoints, clone[i].slopeOrder());
int count = 0;
Point min = null;
Point max = null;
for (int j = 0; j < (tempPointsNum - 1); j++) {
if (clone[i].slopeTo(tempPoints[j]) == clone[i].slopeTo(
tempPoints[j + 1])) {
if (min == null) {
if (clone[i].compareTo(tempPoints[j]) > 0) {
max = clone[i];
min = tempPoints[j];
} else {
max = tempPoints[j];
min = clone[i];
}
}
if (min.compareTo(tempPoints[j + 1]) > 0) {
min = tempPoints[j + 1];
}
if (max.compareTo(tempPoints[j + 1]) < 0) {
max = tempPoints[j + 1];
}
count++;
if (j == (tempPointsNum - 2)) {
if (count >= 2 && clone[i].compareTo(min) == 0) {
addLine(min, max);
}
count = 0;
min = null;
max = null;
}
} else {
if (count >= 2 && clone[i].compareTo(min) == 0) {
addLine(min, max);
}
count = 0;
min = null;
max = null;
}
}
}
}
privatevoidaddLine(Point a, Point b) {
if (last != null) {
Node newNode = new Node();
newNode.prev = last;
newNode.value = new LineSegment(a, b);
last = newNode;
} else {
last = new Node();
last.value = new LineSegment(a, b);
}
lineNumber++;
}
publicintnumberOfSegments() // the number of line segments
{
return lineNumber;
}
public LineSegment[] segments() // the line segments
{
LineSegment[] lines = new LineSegment[lineNumber];
Node current = last;
for (int i = 0; i < lineNumber; i++) {
lines[i] = current.value;
current = current.prev;
}
return lines;
}
publicstaticvoidmain(String[] args) {
// read the n points from a file
In in = new In(args[0]);
int n = in.readInt();
Point[] points = new Point[n];
for (int i = 0; i < n; i++) {
int x = in.readInt();
int y = in.readInt();
points[i] = new Point(x, y);
}
// draw the points
StdDraw.enableDoubleBuffering();
StdDraw.setXscale(0, 32768);
StdDraw.setYscale(0, 32768);
for (Point p : points) {
p.draw();
}
StdDraw.show();
// print and draw the line segments
FastCollinearPoints collinear = new FastCollinearPoints(points);
for (LineSegment segment : collinear.segments()) {
StdOut.println(segment);
segment.draw();
}
StdDraw.show();
}
privateclass Node {
private LineSegment value;
private Node prev;
}
}
BruteCollinearPoints
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;
import java.util.Arrays;
publicclass BruteCollinearPoints {
privateint N;
private Node line; //因为不知道有多少条线,所以最好用链表初始化以节约空间privateclass Node {
LineSegment val;
Node prev;
}
publicBruteCollinearPoints(Point[] points) {
if(points == null)
thrownew java.lang.IllegalArgumentException();
N=0;
int num = points.length;
Point[] clone = new Point[num];
for (int i = 0; i < num; i++) {
if (points[i] == null)
thrownew IllegalArgumentException();
for (int j = i + 1; j < num; j++) {
if (points[i].compareTo(points[j]) == 0)
thrownew IllegalArgumentException();
}
clone[i] = points[i];
}
Arrays.sort(clone);//避免线段起点选在中间点for(int i = 0; i < num -3; i++) {
for (int j = i+1; j<num -2; j++) {
for (int p = j+1; p<num -1; p++) {
for(int q = p+1; q < num; q++) {
double k1 = clone[i].slopeTo(clone[j]);
double k2 = clone[j].slopeTo(clone[p]);
double k3 = clone[p].slopeTo(clone[q]);
if (k1 == k2 && k2 == k3) {
if (line != null) {
Node new_node = new Node();
new_node.prev = line;
new_node.val = new LineSegment(clone[i], clone[q]);
line = new_node; //由于随着增加线段,line 不再指向开头,所以用prev而不是next
}
else{
line = new Node();
line.val = new LineSegment(clone[i], clone[q]);
}
N++;
}
}
}
}
}
} // finds all line segments containing 4 pointspublicintnumberOfSegments() {
return N;
} // the number of line segmentspublic LineSegment[] segments() {
LineSegment[] lines = new LineSegment[N];
Node copy = line; //不改变原数组for (int i = 0; i<N; i++) {
lines[i] = copy.val;
copy = copy.prev;
}
return lines;
}
publicstaticvoidmain(String[] args) {
// read the n points from a file
In in = new In(args[0]);
int n = in.readInt();
Point[] points = new Point[n];
for (int i = 0; i < n; i++) {
int x = in.readInt();
int y = in.readInt();
points[i] = new Point(x, y);
}
// draw the points
StdDraw.enableDoubleBuffering();
StdDraw.setXscale(0, 32768);
StdDraw.setYscale(0, 32768);
for (Point p : points) {
p.draw();
}
StdDraw.show();
// print and draw the line segments
BruteCollinearPoints collinear = new BruteCollinearPoints(points);
for (LineSegment segment : collinear.segments()) {
StdOut.println(segment);
segment.draw();
}
StdDraw.show();
}
}