当前位置:文档之家› 蛮力法分治法求最近对

蛮力法分治法求最近对

实验题目设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。

实验目的(1)进一步掌握递归算法的设计思想以及递归程序的调试技术;(2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。

实验内容(包括代码和对应的执行结果截图)#include<iostream>#include<cmath>#include <windows.h>using namespace std;typedef struct Node{//定义一个点的结构,用于表示一个点int x;int y;}Node;typedef struct NList{//定义一个表示点的集合的结构Node* data;int count;}NList;typedef struct CloseNode{//用于保存最近两个点以及这两个点之间的距离Node a;Node b;double space;}CloseNode;int max;void create(NList & L){cout<<"请输入平面上点的数目:\n";cin>>max;L.count=max;L.data = new Node[L.count];//====================动态空间分配cout<<"输入"<<L.count<<"个点坐标X,Y,以空格隔开:"<<endl;for(int i=0;i<L.count;i++)cin>>L.data[i].x>>L.data[i].y;}//求距离平方的函数double Distinguish2(Node a,Node b){return ((a.x-b.x)*(a.x-b.x))+((a.y-b.y)*(a.y-b.y));}//蛮力法求最近对void BruteForce(const NList & L,CloseNode & cnode,int begin,int end){for(int i=begin;i<=end;i++)for(int j=i+1;j<=end;j++){double space = Distinguish2(L.data[i],L.data[j]);if(space<cnode.space){cnode.a=L.data[i];cnode.b=L.data[j];cnode.space=space;}}}//归并排序void Merge(Node SR[],Node TR[],int i,int m,int n){//将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]int j,k;for(j=m+1,k=i;i<=m&&j<=n;k++)if(SR[i].x<=SR[j].x) TR[k]=SR[i++];else TR[k]=SR[j++];while(i<=m) TR[k++]=SR[i++];while(j<=n) TR[k++]=SR[j++];}void Msort(Node SR[],Node TR1[],int s,int t){//将SR[s..t]归并排序为TR1[s..t]if(s==t) TR1[s]=SR[s];else{int m = (s+t)/2;Node *TR2=new Node[max];//new Node[t-s+1];//这个空间挂挂的,从s到t,这里是从0到t-sMsort(SR,TR2,s,m);Msort(SR,TR2,m+1,t);Merge(TR2,TR1,s,m,t);}}void MergeSort(NList L){Msort(L.data,L.data,0,L.count-1);}//分治法求最近对中间2d对称区的算法void Middle(const NList & L,CloseNode & cnode,int mid,int midX){int i,j;int d = sqrt(cnode.space);i=mid;while(i>=0&&L.data[i].x>=(midX-d)){j=mid;while(L.data[++j].x<=(midX+d)&&j<=L.count){//1,j++ 2<=,>=if(L.data[j].y<(L.data[i].y-d)||L.data[j].y>(L.data[i].y+d))continue;double space = Distinguish2(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 DivideAndConquer(const NList &L,CloseNode & closenode,int begin,int end) {if((end-begin+1)<4) BruteForce(L,closenode,begin,end);else{int mid = (begin+end)/2;int midX = L.data[mid].x;DivideAndConquer(L,closenode,begin,mid);DivideAndConquer(L,closenode,mid+1,end);Middle(L,closenode,mid,midX);}}int main(){SYSTEMTIME sys;GetLocalTime( &sys );NList list;CloseNode closenode;closenode.space = 10000;create(list);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<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;cout<<"最近对为点("<<closenode.a.x<<","<<closenode.a.y<<")和点("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距离为: "<<sqrt(closenode.space)<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;cout<<"==================================================== ================"<<endl;cout<<"用分治法求最近对:"<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;MergeSort(list);cout<<"经过归并排序后的各点:"<<endl;for(int j=0;j<list.count;++j)cout<<"X="<<list.data[j].x<<" Y="<<list.data[j].y<<"\n";DivideAndConquer(list,closenode,0,list.count-1);cout<<"最近对为点("<<closenode.a.x<<","<<closenode.a.y<<")和点("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距离为: "<<sqrt(closenode.space)<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;return 0;}实验结果分析由以上数据可知,分治法效率比蛮力法效率高。

蛮力法求解最近对问题的过程是:分别计算每一对点之间的距离,然后找出距离最小的那一对,为了避免对同一对点计算两次距离,只考虑i <j 的那些点对(Pi , Pj )。

相关主题