princeton algorithms part 1 第三周作业题

本文介绍了一个Point类的实现,该类支持比较、绘制等操作,并提供了计算两点间斜率的方法。此外,还介绍了两种不同的算法:BruteCollinearPoints和FastCollinearPoints,用于检测平面上是否存在四点或更多点共线的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

public class Point implements Comparable<Point> {

    private final int x;     // x-coordinate of this point
    private final 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;
        } else if (this.x == that.x) {
            return Double.POSITIVE_INFINITY;
        } else if (this.y == that.y) {
            return 0;
        } 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)) {
            return 0;
        } else if ((that.y > this.y) ||
                ((that.y == this.y) && (that.x > this.x))) {
            return -1;
        } else {
            return 1;
        }
    }

    /**
     * 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() {
        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;
            }
        }
    }

    /**
     * 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;

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 IllegalArgumentException();
        }

        lineNumber = 0;

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

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

            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;
    }
}


  • BruteCollinearPoints
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 N;
   private Node line; //因为不知道有多少条线,所以最好用链表初始化以节约空间

    private class Node {
        LineSegment val;
        Node prev;
    }

    public BruteCollinearPoints(Point[] points) {
        if(points == null)
            throw new 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)
                throw new IllegalArgumentException();

            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 -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 points

    public int numberOfSegments() {
        return N;
    }        // the number of line segments

    public 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;
    }

    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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值