Programming Assignment: Collinear Points

Point.java

import edu.princeton.cs.algs4.StdDraw;
import java.util.Comparator;

public class Point implements Comparable<Point> {
    private int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void draw() {
        StdDraw.point(this.x, this.y);
    }                              // draws this point

    public void drawTo(Point that) {
        StdDraw.line(this.x, this.y, that.x, that.y);
    }

    public String toString() {
        return "(" + x + ", " + y + ")";
    }


    @Override
    public int compareTo(Point that) {
        if ((this.x == that.x) && (this.y == that.y)) {
            return 0;
        } else if ((that.y > this.y) ||
                ((that.y == this.y) && (that.x > this.x))) {
            return -1;
        } else {
            return 1;
        }
    }


    public double slopeTo(Point point) {
        int dx = point.x - this.x;
        int dy = point.y - this.y;
        if (dx == 0 && dy == 0) return Double.NEGATIVE_INFINITY;
        if (dx == 0) return Double.POSITIVE_INFINITY;
        if (dy == 0) return +0;
        else return (double) dy / (double) dx;
    }

    public Comparator<Point> slopeOrder() {
        return new SlopeOrder(this);
    }

    private class SlopeOrder implements Comparator<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;
            } else if (d01 > d02) {
                return 1;
            } else {
                return 0;
            }
        }
    }


}

LineSegment .java

public class LineSegment {
    private Point p, q;

    public LineSegment(Point p, Point q) {
    }    // constructs the line segment between points p and q

    public void draw() {
    }                 // draws this line segment

    public String toString() {
        return p + " -> " + q;
    }
}

BruteCollinearPoints .java

import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;

import java.util.Arrays;

public class BruteCollinearPoints {
    private int lineNumber;
    private Node last;

    public BruteCollinearPoints(Point[] points) // finds all line segments containing 4 points
    {

        if (points == null) {
            throw new NullPointerException();
        }

        lineNumber = 0;

        int num = points.length;

        Point[] clone = new Point[num];

        for (int i = 0; i < num; i++) {
            if (points[i] == null) {
                throw new NullPointerException();
            }

            for (int j = i + 1; j < num; j++) {
                if (points[i].compareTo(points[j]) == 0) {
                    throw new IllegalArgumentException();
                }
            }
            clone[i] = points[i];
        }
        Arrays.sort(clone);
        for (int i = 0; i < num; i++) {
            for (int j = i + 1; j < num; j++) {
                for (int m = j + 1; m < num; m++) {
                    for (int n = m + 1; n < num; n++) {
                        double d01 = clone[i].slopeTo(clone[j]);
                        double d02 = clone[j].slopeTo(clone[m]);
                        double d03 = clone[m].slopeTo(clone[n]);

                        if (d01 == d02 && d01 == d03) {
                            if (last != null) {
                                Node newNode = new Node();
                                newNode.prev = last;
                                newNode.value = new LineSegment(clone[i],
                                        clone[n]);
                                last = newNode;
                            } else {
                                last = new Node();
                                last.value = new LineSegment(clone[i],
                                        clone[n]);
                            }

                            lineNumber++;
                        }
                    }
                }
            }
        }
    }

    public int numberOfSegments() // 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;
    }

    public static void main(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();
    }

    private class Node {
        private LineSegment value;
        private Node prev;
    }
}

FastCollinearPoints .java

import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;

import java.util.Arrays;

public class FastCollinearPoints {
    private int lineNumber;
    private Node last;

    public FastCollinearPoints(Point[] points) // finds all line segments containing 4 or more points
    {
        if (points == null) {
            throw new NullPointerException();
        }

        lineNumber = 0;

        int num = points.length;
        Point[] clone = new Point[num];

        for (int i = 0; i < num; i++) {
            if (points[i] == null) {
                throw new NullPointerException();
            }

            for (int j = i + 1; j < num; j++) {
                if (points[i].compareTo(points[j]) == 0) {
                    throw new 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;
                }
            }
        }
    }

    private void addLine(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++;
    }

    public int numberOfSegments() // 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;
    }

    public static void main(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();
    }

    private class Node {
        private LineSegment value;
        private Node prev;
    }
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值