当前位置:
文档之家› 中科大软院算法导论最近点对算法_C++
中科大软院算法导论最近点对算法_C++
if (L!=0&&R!=0) {
for (i=l-L+1;i<=l;i++) for (j=l+1;j<=l+R;j++) { if (y[record[j]]-y[record[i]]<Min||-Min<y[record[j]]-y[record[i]]) { mi=lengthf(x[i],y[record[i]],x[j],y[record[j]]); if (mi<Min) { Min=mi; rem1=i; rem2=j; } } }
if (a>=b) return b;
else return a;
} ////////////////////////////对平面数组排序//////////////////////////// void sort(int A[]) {
int i,j; for (i=0;i<N;i++)
record[i]=i; for (j=1;j<N;j++) {
// cout<<"min="<<min<<endl; //cout<<"rem1="<<rem1<<endl<<"rem2="<<rem2<<endl;
}
} return Min; } /***********************************************************************/ //////////////////////////////////主函数/////////////////////////////////// int main() { //double a; randnum(); cout<<"***************************遍历法*************************"<<endl; exhaustion(); cout<<"***************************分治法*************************"<<endl; sort(x); divide(0,N-1); cout<<"元素组中最短距离为:"<<endl; cout<<"min="<<Min<<endl; return 0; }
//三个点时求最大值 return mlength; }
double divide(int left,int right)
{
if (right-left<=2)
{
Min=merge(left,right);
}
else
{
double l1,l2,mi;
//l1 记录划分区域后左半面最小距离,l2
记录右半面最小距离,min 为两者中较小者,m 为全部中的最小者
i=j; while (i>=0&&A[i]<A[i-1])
{ swap(A[i],A[i-1]); swap(record[i-1],record[i]); i--;
} } cout<<"排序后的元素数组:"<<endl; for (i=0;i<N;i++)
cout<<A[i]<<' '; cout<<endl; for (i=0;i<N;i++)
分治法是把一个大的问题划分成相似的小问题,采用递归的思想。找中线把 n 个元 素分成左右两部分元素分别求得两边的最短距离,然后取两者中的最小者记为 l,在中线两 边分别取 l 的距离,记录该距离范围内点的个数,中线左边有 L 个元素,右边有 R 个元素, 求左边元素到右边元素的距离看其是否小于之前记录的最短距离,小则记录下来,此时的右
实验四 求最近点对算法
1.算法设计思路:
设共有 n 个点,找其中距离最近的两点及其距离。 (1)蛮力法: 蛮力法的思路是把所有点之间距离比较找出中间最小的。先假设最短距离是第一个
元素和第二个元素的距离,然后求第一个元素与其后的(n-1)个元素各自的距离,若比之 前记录的最短距离小则记录当前值···求第 i 个元素与其后的(n-i)个元素各自的距离,记 录之前所得到的所有距离中的最小值,直到计算到第(n-1)个元素与第 n 个元素的距离, 此时记录的距离即为这 n 个元素中的最短距离。 (2)分治法:
边元素只取 y 值和左边元素 y 值距离小于 l 的(减少循环次数)。循环结束即可找到最小的 距离。
2.程序代码:
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<cmath>
using std::cout;
using std::endl;
cout<<record[i]<<' '; cout<<end////////////////////穷举法找最小点对/////////////////////////////// double exhaustion() {
int i,j,k1,k2; double num; double length; num=10000; k1=k2=-1; for (j=0;j<N-1;j++) {
cout<<"(x1,y1)="<<'('<<x[k1]<<','<<y[k1]<<')'<<endl<<"(x2,y2)="<<'('<<x[k2]<<','<<y[k2]<<')' <<endl;
return num;
} ////////////////////////////////////分治法/////////////////////////////// /*************************************************************************/
double merge(int left,int right) {
double mlength; if (right==left)
mlength=10e-6; if (right==left+1)
mlength=lengthf(x[right],y[record[right]],x[left],y[record[left]]); if (right-left==2)
l1=divide(left,l);
l2=divide(l+1,right);
if (l1<l2)
{
Min=l1;
//cout<<"两半面最短距离是:"<<min;
} else {
Min=l2; //cout<<"两半面最短距离是:"<<min; } ///////////////////得到右半块元素数 R //cout<<"min="<<min<<endl; for (i=l+1;i<N;i++) { if (x[i]-x[l]<=Min)
3.实验数据及实验结果:
实验数据: 随机产生的五个点坐标分别为:(1,3),(4,2),(3,0),(2,0),(0,3) 实验结果:用蛮力法得到平面数组最短距离为:min=1
用分治法得到平面数组最短距离为:min=1
4.实验总结:
从本次试验中得到的领悟是:分治法事把问题分解成两个相似小问题,子问题和原 来的大问题解决方法一样所以可以用递归,分治法重要是找到递归出口,什么时候递归结束, 一般都有元素个数的限制。并且通过这次试验巩固了排序算法。
int rem1,rem2,l;
//记录获得最短距离对应的两个点
//int il,jl,ir,jr;
int i,j;
int R,L;
R=L=0;
//记录划分小区域后的左半块和右半
块个有多少元素
l1=l2=Min=100;
l=(right-left+1)/2-1;
//中线位置
///////////////////////////////////////////////////
for (i=j+1;i<N;i++) {
length=lengthf(x[i],y[i],x[j],y[j]); if (length<num) {
num=length; k1=i; k2=j; } } } cout<<"平面数组最短距离是:"<<endl; cout<<"min="<<num<<endl; cout<<"对应数组下标及点坐标为:"<<endl; cout<<"i="<<k1<<','<<k2<<endl;