zoukankan      html  css  js  c++  java
  • 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
    参考资料:

    图片

    图片

    图片

    图片

    图片

  • 相关阅读:
    Ubuntu实现树莓派交叉编译
    IOS页面自动布局 之 NSLayoutConstraint基础篇
    环信SDK与Apple Watch的结合(3)
    数据结构C语言版干货------->线性表之顺序表
    Java的反射机制(应用篇)
    Java之泛型深解
    Java集合类--->入门下篇
    Java之泛型浅解
    Java集合类--->入门上篇
    数据结构基础铺垫篇000
  • 原文地址:https://www.cnblogs.com/longjin2018/p/9848802.html
Copyright © 2011-2022 走看看