找到最近的2分

时间:2014-02-10 15:20:16

标签: java algorithm

如果有人可以帮我解决这个问题,那我很想知道:我正在尝试创建一段Java代码,找到距离点最近的2个点。以下是我到目前为止的情况:

import java.util.Random;

public class Main {
  static int distance(int x1, int x2) {
    return Math.round((x2 - x1) * (x2 - x1));
    // Math.sqrt is the square root of the 2 co-ordinates
  }

  public static void main(String[] args) {
    Random randomGenerator = new Random();
    int x2, x1; // The Points
    int distance;// The Math to work out distance
    int randomInt2 = randomGenerator.nextInt(10) + 1;// For Length of array
    int[] distances = new int[randomInt2];// The Array
    int store;

    x1 = 0;// used to calculate distance from original point to current point
    System.out.println("Distance Generated for Point 1 : 0");// For First Point

    int origin = 1;// increment which point start from
    int range = 0;// Amount of Points
    int point = 2;// Counts the number of points
    while (range < randomInt2) {
      int randomInt3 = randomGenerator.nextInt(10) + 2;// Distance for all points besides first
      x2 = randomInt3;
      distance = distance(x1, x2); // System.out.println("The distance between point 1 and point " +point+ " is " + distance + " .");
      System.out.println("Distance from Point " + origin + " to Point " + point + " is distance = " + distance);
      store = distance;// stores the distance to be put into array
      point++;// increments the point number each time
      distances[range] = store;
      // System.out.println(" ,from Point " +point+" to Point "+origin+" = " + distance);
      origin++;// Increments Original Point
      range++;// increments amount of points each time
    }
    /*
     * for (int val : distances) { System.out.println(val); }
     */
  }
}

到目前为止,它创建了具有随机距离的点,并且我能够找到距离前一点的每个点的最近点。但是我试图让它成为一种树形结构,其中每个点都有2个最接近它的点。对不起,如果我没有说清楚,但如果有人能给我任何提示,他们将不胜感激。

1 个答案:

答案 0 :(得分:2)

很难猜出你想做什么。从我如何阅读你的问题,你想在一条线上创建一些点(即一维点),并找到每个点最接近的两个点。

---------甲----------- ---------乙C-d-E -----------

对于线上的这些点A-E,这应该会产生如下结果:
A的邻居是B和C.
B的邻居是A和C.
C的邻居是D和E.
D的邻居是C和E. E的邻居是C和D.

但是您的代码的结果如下:
A与B的距离为d B与C的距离为d C与D的距离为d D与E的距离为d。

关于如何改进代码已有一些建议,我现在将添加这些建议,并列举其他几个。

你的确切问题是什么?

我们现在只能猜测,因为您的代码与您的问题所做的完全不同。再考虑一下,并尝试提出一些更清晰的问题。

尝试思考面向对象

已经提到:最好有一些课程,至少例如Point的一个类。将distance方法放入另一个类,也许是某种数学库可能会很好 还要考虑可见性。包可见性(distance()方法使用的内容)通常不是您的想法。 使用类可以使代码更加结构化,并且通常更容易扩展或增加一些可重用性。

变量名称和代码样式

我们很难猜到rangerandomInt2store的含义。如果你有一个正确的上下文,一个好的缩进和一些有意义的名字,我们可以更容易地猜测它的作用,即使评论较少。

您遇到的另一个问题是您一次又一次地重复使用x2。最终你有一些距离,存储在距离数组中,但不知道它们属于哪一点 - 因为这些点不再存在。

解决问题

好的,虽然你的问题不是最有帮助的,但我会尝试解决问题。

首先想到一个Point类。我决定将其称为Point1D,以表明它可以轻松扩展到Point2D之后或Point3D

package sto;

public class Point1D {
    private final double x; // this could also be a good public variable
    private final String name;

    public Point1D(double x, String name) {
        this.x = x;
        this.name = name;
    }

    public double distanceTo(Point1D other) {
        return Math.abs(other.x - this.x);
    }
}

这可能是一个简单的Point1D课程,可满足您的需求。它包含String name,值(此处为double x)以及计算此Point1D与另一个public double distanceTo(Point1D other)之间距离的方法:Main

在你的package sto; import java.util.Random; public class Main { public static void main(String[] args) { Random rng = new Random(); // generate points int numberOfPoints = rng.nextInt(10) + 1; Point1D[] points = new Point1D[numberOfPoints]; for(int i = 0; i < numberOfPoints; ++i) { points[i] = new Point1D(rng.nextDouble() * 10.0d, "Point " + i); } } } 中,您现在可以创建一个可重复使用的随机数量的点:

Point1D[] points

这将在numberOfPoints数组中创建1-10个点。请注意命名:randomInt2 public static double distance(Point1D p1, Point1D p2) { return p1.distanceTo(p2); } 更有意义。

由于你在main中有一个距离函数,我们也可以添加它。请注意,我们现在使用公共可见性执行此操作,以便可以从任何位置访问它:

MathUtil

将这样的方法移到单独的类中会更好,例如distanceTo(Point1D)。因为我已经创建了 for(int i = 0; i < numberOfPoints; ++i) { Point1D currentPoint = points[i]; Point1D closestPoint = null; Point1D secondClosestPoint = null; for(int j = 0; j < numberOfPoints; ++j) { if(i == j) continue; if(closestPoint == null || currentPoint.distanceTo(points[j]) < currentPoint.distanceTo(closestPoint)) { secondClosestPoint = closestPoint; closestPoint = points[j]; } else if(secondClosestPoint == null || currentPoint.distanceTo(points[j]) < currentPoint.distanceTo(secondClosestPoint)) { secondClosestPoint = points[j]; } } currentPoint.setNeighbors(closestPoint, secondClosestPoint); } ,所以现在还不需要它。

现在您想要找到每个点的两个最近点。可能有比这更好的方法,但这个方法做得很好:

null

首先,我们定义最近和第二个最近的点并用null初始化它们。然后我们比较当前点和其他点之间的距离,每当距离比当前最近点更近时,我们分配它。否则我们检查第二个最近的点。注意points[0]检查,这是为了避免空指针异常和(如果你说:嘿,我可以一直用points[j]currentPoint初始化它)你比较距离为零的情况(如果points[0]等于currentPointpoints[j]等于null),或者您最近和最接近的距离设置为距离最近的点。

另请注意,只有1或2个生成点,一个或两个邻居将为currentPoint.setNeighbors(closestPoint, secondClosestPoint);

最后一个方法调用Point1D对您来说是新手。不知何故,你想存储邻居。而不是真正的树结构(您应该能够使用此答案后的内容构建)我只是决定将邻居存储在Point1D对象本身中。为此, /* extensions for your special case: two neighbors */ private Point1D neighbor1 = null; private Point1D neighbor2 = null; public void setNeighbors(Point1D p1, Point1D p2) { neighbor1 = p1; neighbor2 = p2; } public String toString() { return "Point1D \"" + name + "\" at " + x + ", " + "Neighbors: " + (neighbor1 != null? neighbor1.name + " (" + distanceTo(neighbor1) + "), " : "") + (neighbor2 != null? neighbor2.name + " (" + distanceTo(neighbor2) + ")" : ""); } 类被改变了一点:

public String toString()

Point1D有两个简单的成员和一个setter。当然,您可以轻松地修改它,并使用getter等扩展它。我还重载Point1D以便能够轻松打印package sto; import java.util.Random; public class Main { // better into a seperate MathLibrary public static double distance(Point1D p1, Point1D p2) { return p1.distanceTo(p2); } public static void main(String[] args) { Random rng = new Random(); // generate points int numberOfPoints = rng.nextInt(10) + 1; Point1D[] points = new Point1D[numberOfPoints]; for(int i = 0; i < numberOfPoints; ++i) { points[i] = new Point1D(rng.nextDouble() * 10.0d, "Point " + i); } for(int i = 0; i < numberOfPoints; ++i) { Point1D currentPoint = points[i]; Point1D closestPoint = null; Point1D secondClosestPoint = null; for(int j = 0; j < numberOfPoints; ++j) { if(i == j) continue; if(closestPoint == null || currentPoint.distanceTo(points[j]) < currentPoint.distanceTo(closestPoint)) { secondClosestPoint = closestPoint; closestPoint = points[j]; } else if(secondClosestPoint == null || currentPoint.distanceTo(points[j]) < currentPoint.distanceTo(secondClosestPoint)) { secondClosestPoint = points[j]; } } currentPoint.setNeighbors(closestPoint, secondClosestPoint); } for(int i = 0; i < numberOfPoints; ++i) System.out.println(points[i]); } }

毕竟我们只需要打印它们,这只是另一个非常简单的循环。

完整代码

Main.java

package sto;

public class Point1D {
    private final double x; // this could also be a good public variable
    private final String name;

    public Point1D(double x, String name) {
        this.x = x;
        this.name = name;
    }

    public double distanceTo(Point1D other) {
        return Math.abs(other.x - this.x);
    }

    /* extensions for your special things: 2 neighbors */
    private Point1D neighbor1 = null;
    private Point1D neighbor2 = null;

    public String toString() {
        return "Point1D \"" + name + "\" at " + x + ", "
             + "Neighbors: " + (neighbor1 != null? neighbor1.name + " (" + distanceTo(neighbor1) + "), " : "") 
                             + (neighbor2 != null? neighbor2.name + " (" + distanceTo(neighbor2) + ")" : ""); 
    }

    public void setNeighbors(Point1D p1, Point1D p2) {
        neighbor1 = p1;
        neighbor2 = p2;
    }

}

Point1D.java

Point1D "Point 0" at 6.420136069230588, Neighbors: 

示例输出

生成1点:

Point1D "Point 0" at 5.944088209230237, Neighbors: Point 1 (0.43915003704614364), 
Point1D "Point 1" at 6.383238246276381, Neighbors: Point 0 (0.43915003704614364), 

有2个生成点:

Point1D "Point 0" at 8.843803983191671, Neighbors: Point 8 (1.1272536955360408), Point 3 (1.561097922588882)
Point1D "Point 1" at 5.769064395124087, Neighbors: Point 9 (0.2901718634798556), Point 3 (1.5136416654787022)
Point1D "Point 2" at 3.1745401994446834, Neighbors: Point 7 (0.23098459949774464), Point 5 (0.2711748146393602)
Point1D "Point 3" at 7.28270606060279, Neighbors: Point 9 (1.2234698019988466), Point 1 (1.5136416654787022)
Point1D "Point 4" at 1.3174388168729179, Neighbors: Point 5 (1.5859265679324053), Point 7 (1.6261167830740209)
Point1D "Point 5" at 2.903365384805323, Neighbors: Point 7 (0.04019021514161558), Point 2 (0.2711748146393602)
Point1D "Point 6" at 3.8143932773804448, Neighbors: Point 2 (0.6398530779357614), Point 7 (0.870837677433506)
Point1D "Point 7" at 2.9435555999469387, Neighbors: Point 5 (0.04019021514161558), Point 2 (0.23098459949774464)
Point1D "Point 8" at 9.971057678727712, Neighbors: Point 0 (1.1272536955360408), Point 3 (2.6883516181249227)
Point1D "Point 9" at 6.059236258603943, Neighbors: Point 1 (0.2901718634798556), Point 3 (1.2234698019988466)

超过2分:

public static double distance(PointND p1, PointND p2)

运动

尝试为Point2D和Point3D实现此功能,在单独的MathUtil.java中使用{{1}}。