0

現在、Convex HUll と連携して Graham's Scan に取り組んでいます。私は学生なので、自分でやろうとしていますが、答えを見つけるために複数のサイトをふるいにかけています。要するに、ファイルから 1 つとランダムに生成された 1 つのコンストラクターが動作しているので、ポイントの配列を作成できます。次のステップは、極角でソートするクイックソートを実装することです。これは、比較クラスを介して行われます。比較クラスは私が立ち往生しているところです。角度の比較を行うためにドット比較とクロス比較を使用するように言われていますが、かなり迷っています。

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

これらすべてのメソッドで、2 つの Point オブジェクトが等しいかどうかを確認する必要がある場合は、 "==" ではなく、Point の equals メソッドを使用する必要があります。

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

比較の実装

比較メソッドは、その実装で equals()、comparePolarAngle()、および compareDistance() を使用する必要があることに注意してください。また、条件の最後のセット (return 1) は、else ステートメントで処理できます。

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

比較距離の実装

ここで必要な主な情報は、内積のみを使用して、referencePoint から Point オブジェクトへのベクトルの長さを決定する方法です。まず、入力として 2 つの Point を取り、内積を整数値として返すヘルパー メソッドを実装しましょう。

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
}

では、これを使用してベクトルの長さを計算するにはどうすればよいでしょうか? Point とそれ自体の内積を取ると、ピタゴラスの定理 (a^2 + b^2 = c^2) の左辺である(x x) + (y y) が得られます。したがって、dotProduct(p1, p1) を呼び出すと、そのベクトルの長さの 2 乗が得られます。次に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;
   }
}

内積の平方根を取る必要はありません。長さの 2 乗を比較するだけです。また、ポイントではなく整数を比較しているため、ここでは「==」を使用しても問題ないことに注意してください。

comparePolarAngle の実装

内積と同様に、2 つの入力 Point の外積を計算するヘルパー メソッドを実装しましょう。

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
}

2 点の外積をとった結果を別の書き方で表すと、|p1||p2|sin(theta) となります。p1 のベクトル |p2| の長さです。は p2 のベクトルの長さ、シータは p1 から p2 までの角度です。

基準点に対して極角が同じ 2 つの点のシータ値はゼロです。sin(0) = 0 なので、極角が同じ 2 点の外積はゼロです。

基準点に対する p1 の極角が p2 の極角より小さい場合、p1 から p2 までの角度は正になります。0 < theta < 180 の場合、sin(theta) は正です。したがって、p1 と p2 の外積を取り、それが正の場合、p1 の極角は p2 の極角より小さくなければなりません。

基準点に対する p1 の極角が p2 の極角より大きい場合、p1 から p2 への角度は負になります。-180 < theta < 0 の場合、sin(theta) は負です。したがって、p1 と p2 の外積を取り、それが負の場合、p1 の極角は p2 の極角より大きくなければなりません。

この情報を使用して、最終的に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;
   }
}

あなたの Point オブジェクトがどのように保存され、アクセスされ、比較されているか分からないので、クイックソートの実装はあなたに任せます。

于 2015-10-15T23:02:31.483 に答える