0

目前正在与 Convex HUll 一起使用 Graham's Scan。我是一名学生,所以我试图自己完成它,但是我一直在筛选多个站点以找到答案。简而言之,我有我的构造函数,一个来自文件,一个随机生成,可以工作,所以我能够创建一个点数组。下一步是实现快速排序,按极角排序。这是通过比较器类完成的。比较器类是我卡住的地方,我们被告知使用点比较和交叉比较来比较角度,但我很迷茫。

/**
 * Use cross product and dot product to implement this method.  Do not take square roots 
 * or use trigonometric functions. See the PowerPoint notes on how to carry out cross and 
 * dot products. 
 * 
 * Call comparePolarAngle() and compareDistance(). 
 * 
 * @param p1
 * @param p2
 * @return -1 if one of the following three conditions holds: 
 *                a) p1 and referencePoint are the same point but p2 is a different point; 
 *                b) neither p1 nor p2 equals referencePoint, and the polar angle of 
 *                   p1 with respect to referencePoint is less than that of p2; 
 *                c) neither p1 nor p2 equals referencePoint, p1 and p2 have the same polar 
 *                   angle w.r.t. referencePoint, and p1 is closer to referencePoint than p2. 
 *         0  if p1 and p2 are the same point  
 *         1  if one of the following three conditions holds:
 *                a) p2 and referencePoint are the same point but p1 is a different point; 
 *                b) neither p1 nor p2 equals referencePoint, and the polar angle of
 *                   p1 with respect to referencePoint is greater than that of p2;
 *                c) neither p1 nor p2 equals referencePoint, p1 and p2 have the same polar
 *                   angle w.r.t. referencePoint, and p1 is further to referencePoint than p2. 
 *                   
 */
public int compare(Point p1, Point p2){
    if(p1 == referencePoint && p2 != referencePoint){
        return -1;
    } else if(p1 == p2){
        return 0;
    } else {

    }
    return 0; 
}


/**
 * Compare the polar angles of two points p1 and p2 with respect to referencePoint.  Use 
 * cross products.  Do not use trigonometric functions. 
 * 
 * Precondition:  p1 and p2 are distinct points. 
 * 
 * @param p1
 * @param p2
 * @return   -1  if p1 equals referencePoint or its polar angle with respect to referencePoint
 *               is less than that of p2. 
 *            0  if p1 and p2 have the same polar angle. 
 *            1  if p2 equals referencePoint or its polar angle with respect to referencePoint
 *               is less than that of p1. 
 */
public int comparePolarAngle(Point p1, Point p2){
    // TODO 
    return 0; 
}


/**
 * Compare the distances of two points p1 and p2 to referencePoint.  Use dot products. 
 * Do not take square roots. 
 * 
 * @param p1
 * @param p2
 * @return   -1   if p1 is closer to referencePoint 
 *            0   if p1 and p2 are equidistant to referencePoint
 *            1   if p2 is closer to referencePoint
 */
public int compareDistance(Point p1, Point p2){
    int distance = 0;

    return distance; 
}

就是这样,在卡住之前,我只是在比较方法上经历了一些小事情。

quickSort 和 partition 方法非常标准,但我将添加它们,以便你们可以广泛了解所有内容:

/**
 * Sort the array points[] in the increasing order of polar angle with respect to lowestPoint.  
 * Use quickSort.  Construct an object of the pointComparator class with lowestPoint as the 
 * argument for point comparison.  
 * 
 * Ought to be private, but is made public for testing convenience.   
 */
public void quickSort(){

    // TODO 
}


/**
 * Operates on the subarray of points[] with indices between first and last. 
 * 
 * @param first  starting index of the subarray
 * @param last   ending index of the subarray
 */
private void quickSortRec(int first, int last){

    // TODO
}


/**
 * Operates on the subarray of points[] with indices between first and last.
 * 
 * @param first
 * @param last
 * @return
 */
private int partition(int first, int last){

    // TODO 
    return 0; 
}

我知道我基本上需要启动并运行 Compare 类,然后才能启动快速排序方法,但我觉得我什至根本不知道如何使用点/交叉比较,所以我真的很迷茫。

如果有人愿意提供帮助,我将不胜感激!非常感谢您的观看,祝您有个愉快的夜晚。

4

1 回答 1

2

In all of these methods, when you need to see if two Point objects are equal you should use Point's equals method, not "==" :

if(p1.equals(p2)) {
    //code
}

Implementing compare

Notice that your compare method needs to use equals(), comparePolarAngle(), and compareDistance() in it's implementation. Also the last set of conditions (return 1) can just be taken care of in an else statement.

public int compare(Point p1, Point p2) {
   if(p1.equals(p2)) {
      return 0;
   }
   else if(p1.equals(referencePoint) ||
          (!p1.equals(referencePoint) && !p2.equals(referencePoint) && comparePolarAngle(p1, p2) == -1) ||
          (!p1.equals(referencePoint) && !p2.equals(referencePoint) && comparePolarAngle(p1, p2) == 0 && compareDistance(p1, p2) == -1))
   {
      return -1;
   }
   else {
      return 1;
   }
}

Implementing compareDistance

The main piece of information that we need here is how to determine the length of the vector from referencePoint to a Point object using only dot products. First, lets implement a helper method that takes two Points as input and returns the dot product as an integer value.

private int dotProduct(Point p1, Point p2) {
   int p1X = p1.getX() - referencePoint.getX();
   int p1Y = p1.getY() - referencePoint.getY();
   int p2X = p2.getX() - referencePoint.getX();
   int p2Y = p2.getY() - referencePoint.getY();
   //compensate for a reference point other than (0, 0)

   return (p1X * p2X) + (p1Y * p2Y);  //formula for dot product
}

So how can we use this to calculate the length of a vector? If we take the dot product of a Point with itself, we get (xx) + (yy) which is the left side of the Pythagorean Theorem (a^2 + b^2 = c^2). So if we call dotProduct(p1, p1), we will get the length of its vector squared. Now lets implement compareDistance.

public int compareDistance(Point p1, Point p2) {
   if(dotProduct(p1, p1) == dotProduct(p2, p2)) {
      return 0;
   }
   else if(dotProduct(p1, p1) < dotProduct(p2, p2)) {
      return -1;
   }
   else {
      return 1;
   }
}

Taking the square root of the dot product is not needed, you can just compare the squared lengths. Also note that "==" is fine to use here because we are comparing integers, not Points.

Implementing comparePolarAngle

As with dot product, lets implement a helper method that computes the cross product of two input Points.

private int crossProduct(Point p1, Point p2) {
   int p1X = p1.getX() - referencePoint.getX();
   int p1Y = p1.getY() - referencePoint.getY();
   int p2X = p2.getX() - referencePoint.getX();
   int p2Y = p2.getY() - referencePoint.getY();
   //compensate for a reference point other than (0, 0)

   return (p1X * p2Y) - (p2X * p1Y);  //formula for cross product
}

Another way of writing the result of taking the cross product of two points is |p1||p2|sin(theta) where |p1| is the length of p1's vector, |p2| is the length of p2's vector and theta is the angle from p1 to p2.

Two points with the same polar angle with respect to the reference point have a theta value of zero. sin(0) = 0, so the cross product of two points with the same polar angle is zero.

If p1's polar angle with respect to the reference point is less than that of p2, the angle from p1 to p2 is positive. For 0 < theta < 180, sin(theta) is positive. Therefore, if we take the cross product of p1 and p2 and it is positive, p1's polar angle must be less that that of p2.

If p1's polar angle with respect to the reference point is greater than that of p2, the angle from p1 to p2 would be negative. for -180 < theta < 0, sin(theta) is negative. Therefore, if we take the cross product of p1 and p2 and it is negative, p1's polar angle must be greater than that of p2.

Using this information, we can finally implement comparePolarAngle.

public int comparePolarAngle(Point p1, Point p2) {
   if(crossProduct(p1, p2) == 0) {
      return 0;
   }
   else if(p1.equals(referencePoint) || crossProduct(p1, p2) > 0) {
      return -1;
   }
   else {
      return 1;
   }
}

I will leave the implementation of quick sort to you, as I don't know how your Point objects are being stored, accessed and compared.

于 2015-10-15T23:02:31.483 回答