之前的最近点计算,是使用暴力搜索的,所需的时间让人不可接受
利用哈希算法,将单位正方形分成一个网格,设置一个链表的二维数组,每个网格正方形对应一个表,选择的网格足够精巧,与已知距离为d之内的所有点或落于统一网格内,或落于邻接网格内!
解读:就是将距离哈希化,对应的坐标落在某一个格子里面,每个格子都有一个头指针,存储映射到其内的坐标,相邻的坐标之差都是比1来得小的,所以只需要与周围的8个格子内的坐标及其当前格子内的坐标进行比较即可
补充:
二维数组的建立:
link **malloc2d(int r,int c)
{
int i;
link **t = (link **)malloc(r*sizeof(link *));
for(i = 0;i < r;i++)
t[i] = (link *)malloc(c*sizeof(link));
return t;
}
二维数组的删除:
void Free(link **tmp,int row)
{
int i = 0;
for(i = 0;i < row;i++)
{
free(tmp[i]);
}
free(tmp);
}
注:t[i][j]已经就是对对应指针所指向的元素的访问,而(*t[i])与之是等价的。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct Point
{
float x;
float y;
}point;
float randFloat()
{
return 1.0*rand()/RAND_MAX;
}
float distance(Point a,Point b)
{
return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
typedef struct node* link;
struct node
{
point p;
link next;
};
link **malloc2d(int r,int c)
{
int i;
link **t = (link **)malloc(r*sizeof(link *));
for(i = 0;i < r;i++)
t[i] = (link *)malloc(c*sizeof(link));
return t;
}
void Free(link **tmp,int row)
{
int i = 0;
for(i = 0;i < row;i++)
{
free(tmp[i]);
}
free(tmp);
}
link **grid;
int G;
float d;
int cnt = 0;
void gridinsert(float x,float y)
{
int i,j;
link s;
int X = x*G + 1;
int Y = y*G + 1;
link t = (link)malloc(sizeof(struct node));
t->p.x = x;
t->p.y = y;
for(i = X-1;i <= X+1;i++)
{
for(j = Y-1;j <= Y+1;j++)
{
for(s = grid[i][j];s!=NULL;s = s->next)
{
if(distance(s->p,t->p) < d)
cnt++;
}
}
}
t->next = grid[X][Y];
grid[X][Y] = t;
}
int main()
{
int i,j,N;
float x,y;
while(1)
{
cnt = 0;
scanf("%f%d",&d,&N);
//必须用1/d
G = ceil(1/d);//确定网格个数
grid = malloc2d(G+2,G+2);
for(i = 0;i <G+2;i++)
{
for(j = 0;j < G+2;j++)
{
//必须初始化,gird[i][j]相当于是一个头节点
grid[i][j] = NULL;
}
}
for(i = 0;i < N;i++)
{
x = randFloat();
y = randFloat();
gridinsert(x,y);
}
printf("%d shorter than %f\n",cnt,d);
Free(grid,G+2);
}
}
//int main()
//{
// link *s = (link *)malloc(3*sizeof(link));
// //是分配指针 不是分配空间!
// s[0] = (link)malloc(sizeof(struct node));
// s[0]->p.x = 5;
// printf("%f\n",s[0]->p.x);
//}