1. 程式人生 > >分治法求解平面n點中距離最近的兩點

分治法求解平面n點中距離最近的兩點

步驟4:將L-d~L+d內的點以y值排序,對於每一個點(x1,y1)找出y值在y1-d~y1+d內的所有點,計算距離為d'。                 如果d'小於d,令d=d',最後的d值就是答案。

實驗1  遞迴與分治演算法

一,實驗目的和要求

(1)進一步掌握遞迴演算法的設計思想以及遞迴程式的除錯技術;

(2)理解這樣一個觀點:分治與遞迴經常同時應用在演算法設計之中。

(3)分別用蠻力法和分治法求解最近對問題;

(4)分析演算法的時間效能,設計實驗程式驗證分析結論。

二,實驗內容

設p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n個點構成的集合S,設計演算法找出集合S中距離最近的點對。

三,實驗環境

 Turbo C 或VC++

四,實驗學時

    2學時,必做實驗

五,資料結構與演算法

#include<iostream.h>

#include<cmath>

#define TRUE 1

#define FALSE 0

 

typedef struct Node

{

   double x;

   double y;

}Node;       //座標

 

typedef struct List

{

    Node* data;      //點

    int count;      //點的個數

}List;

 

typedef struct CloseNode  

{

    Node a;

    Node b;     //計算距離的兩個點

    double space;     //距離平方

}CloseNode;

 

int n;     //點的數目

 

//輸入各點到List中

void create(List &L)

{

   cout<<"請輸入平面上點的數目:\n";

   cin>>n;

   L.count=n;

   L.data = new Node[L.count];      //動態空間分配

   cout<<"輸入各點座標 :x_y):"<<endl;

   for(int i=0;i<L.count;++i)

      cin>>L.data[i].x>>L.data[i].y;

}

 

//求距離的平方

double square(Node a,Node b)

{

    return ((a.x-b.x)*(a.x-b.x))+((a.y-b.y)*(a.y-b.y));

}

 

//蠻力法

void BruteForce(const List &L,CloseNode &cnode,int begin,int end)

{

   for(int i=begin;i<=end;++i)

   {

      for(int j=i+1;j<=end;++j)

      {

        double space=square(L.data[i],L.data[j]);

        if(space<cnode.space)

        {

           cnode.a=L.data[i];

           cnode.b=L.data[j];

           cnode.space=space;

        }

      }

   }

}

 

//氣泡排序

void BubbleSort(Node r[],int length)

{

    int change,n;

    n=length;change=TRUE;

    double b,c;

    for(int i=0;i<n-1&&change;++i)

    {

        change=FALSE;

        for(int j=0;j<n-i-1;++j)

        {

            if(r[j].x>r[j+1].x)

            {

                b=r[j].x;c=r[j].y;

                r[j].x=r[j+1].x;r[j].y=r[j+1].y;

                r[j+1].x=b;r[j+1].y=c;

                change=TRUE;

            }

        }

    }

}

 

//分治法中先將座標按X軸從小到大的順序排列

void paixu(List L)    

{

   BubbleSort(L.data,L.count);   //呼叫氣泡排序

}

 

//左右各距中線d的區域的最近對演算法

void middle(const List & L,CloseNode &cnode,int mid,double midX)

{

   int i,j;    //分別表示中線左邊,右邊的點

   double d=sqrt(cnode.space);

   i=mid;

   while(i>=0&&L.data[i].x>=(midX-d))    //在左邊的d區域內

   {

     j=mid;

     while(L.data[++j].x<=(midX+d)&&j<=L.count)    //在右邊的d區域內

     {   

        if(L.data[j].y<(L.data[i].y-d)||L.data[j].y>(L.data[i].y+d))   //判斷縱座標是否在左邊某固定點的2d區域內

        continue;

        double space = square(L.data[i],L.data[j]);

        if(cnode.space>space)    //在滿足條件的區域內依次判斷

        {

          cnode.a=L.data[i];

          cnode.b=L.data[j];

          cnode.space=space;

        }

     }

   --i;

   }

}

 

//分治法求最近對

void DivideConquer(const List &L,CloseNode &closenode,int begin,int end)

{

    if(begin!=end)

    {

       int mid = (begin+end)/2;     //排列後的中間的那個點

       double midX = L.data[mid].x;

       DivideConquer(L,closenode,begin,mid);      //繼續在左半邊用分治法求最近對

       DivideConquer(L,closenode,mid+1,end);      //繼續在右半邊用分治法求最近對

       middle(L,closenode,mid,midX);               //判斷左右各距中線d的區域,是否有最近對

    }

}

 

void main()

{

   //初始化

   List list;

   CloseNode closenode;
   closenode.square=10000;//必須付初值,根據實際情況而定


   closenode.space = 10000;    //最近點的距離

 

   create(list);     //輸入各點到NList中

   cout<<"各點座標為:"<<endl;

   for(int i=0;i<list.count;++i)

       cout<<"X="<<list.data[i].x<<"   Y="<<list.data[i].y<<"\n";

   BruteForce(list,closenode,0,list.count-1);

   cout<<"用蠻力法求最近對:"<<endl;

   cout<<"最近對為點 ("<<closenode.a.x<<","<<closenode.a.y<<")和點("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距離為: "<<sqrt(closenode.space)<<endl;

   cout<<endl<<endl;

 

   cout<<"用分治法求最近對:"<<endl;

   paixu(list);

   cout<<"經過排序後的各點:"<<endl;

   for(int j=0;j<list.count;++j)

       cout<<"X="<<list.data[j].x<<"   Y="<<list.data[j].y<<"\n";

   DivideConquer(list,closenode,0,list.count-1);

   cout<<"最近對為點 ("<<closenode.a.x<<","<<closenode.a.y<<")和點("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距離為: "<<sqrt(closenode.space)<<endl;

}