分治法实现最近对问题

分治法----最近对问题

问题描述:

  • 已知有n个点的集合,找出其中最近的一对并返回其最近距离。

解题思路:

  • 这道题的排序是对存入数组的下标进行操作的。
  • 其思路首先是得出所要求的点的个数,再生成随机的点,然后再将所要求的点的坐标依次放入一个结构体数组中,再分别将第一次和最后一次存入的数组的数组下标作为分治法要求的左边界和右边界,再求得其中间的边界,通过递归调用左边界和右边界返回左边界和右边界中的最近点的距离(d=min(d1,d2))。
  • 最近点还有可能在两个集合之间(一个在左边界一个在右边界)。且距离小于d,然后返回最小的距离。

在这里插入图片描述

// 190506分治法求最近对.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include"math.h"
#include"stdlib.h"

#define min(x,y) (x<y)?x:y

#define MAX 10000

typedef struct node{

	int x;
	int y;

}z[MAX];//并命名为一个关于坐标的数组
double distance(node z1, node z2)
{

	double t;
	t = (z1.x - z2.x)*(z1.x - z2.x) + (z1.y - z2.y)*(z1.y - z2.y);

	return sqrt(t);

}//返回距离
double division(node s[], int left, int right)
{
	if (right - left == 1)//当只有两个点时
	{

		return distance(s[right], s[left]);
	}
	if (right - left == 2)//当只有三个点时
	{
		double d1 = distance(s[right], s[left]);
		double d2 = distance(s[right], s[left + 1]);
		double d3 = distance(s[left + 1], s[left]);
		d2 = min(d1, d2);
		d3 = min(d2, d3);//互相两两比较找出三个点的最短距离
		return d3;
	}
	int m = (right + left) / 2;
	int i, j;
	double d1 = division(s, left, m);
	double d2 = division(s, m + 1, right);
	double d = min(d1, d2);
	while (d< s[m].x - s[left].x  &&left <= right)//排除x之差大于d的坐标并且小于右边边界,筛选距离最小的坐标
	{
		left++;
	}
	while (d < s[right].x - s[m].x&&right >= left)
	{
		right--;

	}
	double d3;
	for (i = left; i <= right; i++){
		for (j = i + 1; j <= right; j++)
		{
			if (s[j].y - s[i].y >= d){

				break;//排除y之差大于d的坐标
			}

			else {

				d3 = distance(s[i], s[j]);
				if (d3 < d)
					
					d = d3;
			

			}
		}
	}


	return d;

}


void main()
{
	struct node z[MAX];
	int i, j;
	int n;
	printf("请输入要生成的点数:");
	scanf_s("%d", &n);
	if (n < 2)
	{
		printf("输入错误");
		exit(0);
	}
	for (i = 0; i < n; i++)
	{		
		z[i].x = rand() % 100 + 1;//随机生成100以内的数字
		z[i].y = rand() % 100 + 1;
		for (j = 0; j < i; j++)
		{
			if (z[j].x == z[i].x&&z[i].y == z[j].y){
				
				i--;//检验点集是否重复
				break;
			}

		}

	}
	for (i = 0; i < n; i++)
	{
		printf("(%d,%d)    ", z[i].x, z[i].y);

	}
	printf("最近对最小距离为%lf\n", division(z, 0, n - 1));



}
  • 运行结果:
    在这里插入图片描述
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值