刚写的作业,就贴核心的这一段。求最近点对之前要两次排序。
public static Pair closePair(Point1[] x, Point2[] y, Point2[] z, int left, int right){
if(right-left == 1)//2点情形
return new Pair(x[left], x[right], dist(x[left], x[right]));
if(right-left == 2){//3点情形
double d1 = dist(x[left], x[left+1]);
double d2 = dist(x[right], x[left+1]);
double d3 = dist(x[left], x[right]);
if(d1<=d2 && d1<=d3)
return new Pair(x[left], x[left+1], d1);
if(d2<=d3)
return new Pair(x[left+1], x[right], d2);
else
return new Pair(x[left], x[right], d3);
}
//多于3点的情形,分治法解决
int mid = (left+right)/2;
int i, j, k;
for(i=left, j=left, k=mid+1; i<=right; i++){
if(y[i].p>mid)
z[k++] = y[i];
else
z[j++] = y[i];
}
//递归求解
Pair dp1 = closePair(x, z, y, left, mid);
Pair dp2 = closePair(x, z, y, mid+1, right);
if(dp1.dist > dp2.dist)
dp1 = dp2;
merge(y, z, left, mid, right);//数组z左右部分分别是对y坐标有序的, 将其合并到y数组
//将d矩形条内的点置于z[]中
for(i=left, k=left; i<=right; i++){
if(Math.abs(x[mid].x-y[i].x)<dp1.dist)
z[k++] = y[i];
}
//搜索z[]
for(i=left; i<k; i++){
for(j=i+1; j<k && (z[j].y-z[i].y)<dp1.dist; j++){
double dp = dist(z[i], z[j]);
if(dp<dp1.dist)
dp1 = new Pair(x[z[i].p], x[z[j].p], dp);
}
}
return dp1;
}