Algs4-1.2.1编写一个Point2D的用例-分治法
Posted 修电脑的龙生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Algs4-1.2.1编写一个Point2D的用例-分治法相关的知识,希望对你有一定的参考价值。
1.2.1编写一个Point2D的用例,从命令行接受一个整数N。在单位正方形中生成N个随机点,然后计算两点之间的最近距离。
解:采用分治法。参考资料《算法导论》中文版第三版。
代码实现过程中不太好处理的地方是:为了在Y‘数组中只检查后续7个点而又不在递归中对Y数组进行排序的部分,这就需要确保从排序好的Y数组在O(n)内获取YLeft与YRight的有序数组。
处理的思路是将原始点集复制到数组X,在X中保存点坐标和原始点集数组的索引,然后对X数组按x坐标升序排序,然后再X的坐原和X的索引存入Y数组,再对Y数组的y坐标升序排序。在Y数组中保存X的索引是在O(n)时间区分YLeft与YRight的关键,不足之处是将int型索引存入到double数组元素中,从而过多的出现了类型转换,希望有更完美的处理方案,如有请告之。
代码如下:
import java.util.Arrays;
import java.util.Comparator;
public class Test
{
private static double DistOfFinfinity;
private static class closestPairePoint
{
int Point1;
int Point2;
}
public static void main(String[] args)
{
int N=Integer.parseInt(args[0]);
double start=0;
double width=200;
DistOfFinfinity=2*width*width;
//generate points.
double x,y;
Point2D[] pointArray=new Point2D[N];
double[][] pX=new double[N][3];
double[][] pY=new double[N][3];
for(int i=0;i<N;i++)
{
x=StdRandom.uniform(start,width);
y=StdRandom.uniform(start,width);
pointArray[i]=new Point2D(x,y);
//
pX[i][0]=i;
pX[i][1]=x;
pX[i][2]=y;
}
// order pX by X asc
Arrays.sort(pX,new Comparator<double[]>() {
@Override
public int compare(double[] x, double[] y) {
if(x[1] > y[1]) return 1;
else if (x[1] < y[1]) return -1;
else
{
return 0;
}
}
});
for (int i=0;i<N;i++)
{
//
pY[i][0]=i;
pY[i][1]=pX[i][1];
pY[i][2]=pX[i][2];
}
// order pY by Y asc
Arrays.sort(pY,new Comparator<double[]>() {
@Override
public int compare(double[] x, double[] y) {
if(x[2] > y[2]) return 1;
else if (x[2] < y[2]) return -1;
else
{
return 0;
}
}
});
//find closest pair of point.
closestPairePoint closestPoint = new closestPairePoint();
closestPoint.Point1=-1;
closestPoint.Point2=-1;
double closestDist=DistOfFinfinity;
if (N==0)
{
StdOut.printf("No point!");
return;
}
else if (N==1)
{
StdOut.printf("Only one point!");
return;
}
else if (N<=3)
{
double dist;
for(int i=0;i<N;i++)
{
for(int j=i+1;j<N;j++)
{
dist=pointDist(pX[i][1],pX[i][2],pX[j][1],pX[j][2]);
if (closestDist>dist)
{
closestDist=dist;
closestPoint.Point1=i;
closestPoint.Point2=j;
}//end if
}//end for j
}//end for i
}// end if N<=3
else if(N>3)
{
closestDist = closestTwoPoint (pX,0,pX.length-1,pY, closestPoint);
}//end if N>3
//draw all points
StdDraw.setXscale(start,width);
StdDraw.setYscale(start,width);
StdDraw.setPenRadius(0.005);
for(int i=0;i<N;i++)
{
pointArray[i].draw();
}
//draw closestDist pair of points
StdOut.printf("closestPointOne=%d,closestPointTwo=%d", closestPoint.Point1, closestPoint.Point2);
StdDraw.setPenRadius(0.01);
StdDraw.setPenColor(StdDraw.RED);
closestPoint.Point1=(int)pX[ closestPoint.Point1][0];
closestPoint.Point2=(int)pX[ closestPoint.Point2][0];
pointArray[ closestPoint.Point1].draw();
pointArray[ closestPoint.Point2].draw();
}//end main
private static double closestTwoPoint(double[][] pX, int loX,int hiX,double[][] pY, closestPairePoint closestPoint)
{
double closestDist=DistOfFinfinity;
//return
if ((hiX-loX+1)<=3)
{
double dist;
for(int i=loX;i<=hiX;i++)
{
for(int j=i+1;j<=hiX;j++)
{
dist=pointDist(pX[i][1],pX[i][2],pX[j][1],pX[j][2]);
if (closestDist>dist)
{
closestDist=dist;
closestPoint.Point1=i;
closestPoint.Point2=j;
}//end if (closestDist>dist)
}//end for j
}//end for i
}//end if ((hi-lo+1)<4)
else
{
//divide
closestPairePoint closestPointLeft=new closestPairePoint();
closestPointLeft.Point1=-1;
closestPointLeft.Point2=-1;
closestPairePoint closestPointRigth=new closestPairePoint();
closestPointRigth.Point1=-1;
closestPointRigth.Point2=-1;
int midX=loX+(hiX-loX)/2;
double[][] pYLeft=new double[midX-loX+1][3];
double[][] pYRight=new double[hiX-midX][3];
int Yleft=0;
int Yright=0;
for (int i=0;i<pY.length;i++)
{
if ((int)pY[i][0]>=loX && (int)pY[i][0]<=midX)
{
// StdOut.printf("pYleft length=%d,Yleft=%d
",pYLeft.length,Yleft);
pYLeft[Yleft][0]=pY[i][0];
pYLeft[Yleft][1]=pY[i][1];
pYLeft[Yleft][2]=pY[i][2];
Yleft++;
}
else
{
//StdOut.printf("pYleft length=%d,Yleft=%d
",pYLeft.length,Yleft);
pYRight[Yright][0]=pY[i][0];
pYRight[Yright][1]=pY[i][1];
pYRight[Yright][2]=pY[i][2];
Yright++;
}
}//end divide pYLeftpYRight
//find closest paire point from XLeft and XRight.
double closestDistLeft=closestTwoPoint(pX,loX,midX,pYLeft, closestPointLeft);
double closestDistRight=closestTwoPoint(pX,midX+1,hiX,pYRight, closestPointRigth);
if (closestDistLeft<closestDistRight)
{
closestDist= closestDistLeft;
closestPoint.Point1=closestPointLeft.Point1;
closestPoint.Point2=closestPointLeft.Point2;
}
else
{
closestDist =closestDistRight;
closestPoint.Point1=closestPointRigth.Point1;
closestPoint.Point2=closestPointRigth.Point2;
}//end find closest paire point from XLeft or XRight.
//generate Y‘ (is name pY2)
double[][] pY2=new double[pY.length][3];
int pY2Index=0;
for (int i=0;i<pY.length;i++)
{
if (Math.abs(pY[i][1]-pX[midX][1])<closestDist)
{
pY2[pY2Index][0]=pY[i][0];
pY2[pY2Index][1]=pY[i][1];
pY2[pY2Index][2]=pY[i][2];
pY2Index++;
}
}
//find closest paire point from XLeft and XRight.
double mergeDist;
for (int i=0;i<pY2Index;i++)
for (int j=i+1;j<pY2Index && j<i+8;j++)
{
mergeDist=pointDist(pY2[i][1],pY2[i][2],pY2[j][1],pY2[j][2]);
if (mergeDist<closestDist)
{
closestDist= mergeDist;
closestPoint.Point1=(int)pY2[i][0];
closestPoint.Point2=(int)pY2[j][0];
}
}
}//end else
return closestDist;
}//end closestTwoPoint
private static double pointDist (double x1,double y1,double x2,double y2)
{
return Math.sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
}//end class Test
参考资料:
以上是关于Algs4-1.2.1编写一个Point2D的用例-分治法的主要内容,如果未能解决你的问题,请参考以下文章