编写一段C语言代码要求计算输出n个点中距离最近的两个点的距离,要求时间复杂度低于O(n^2)
时间: 2024-05-15 13:15:36 浏览: 82
两个数相加c语言
这道题可以使用分治法来解决,时间复杂度为O(nlogn)。具体实现如下:
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct point {
double x, y;
};
int cmp_x(const void* a, const void* b) { // 按x坐标升序排序
struct point* p1 = (struct point*)a;
struct point* p2 = (struct point*)b;
return (p1->x > p2->x);
}
int cmp_y(const void* a, const void* b) { // 按y坐标升序排序
struct point* p1 = (struct point*)a;
struct point* p2 = (struct point*)b;
return (p1->y > p2->y);
}
double distance(struct point p1, struct point p2) { // 计算两个点之间的距离
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
double brute_force(struct point* p, int n) { // 暴力求解,时间复杂度为O(n^2)
double min_dist = INFINITY;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
double d = distance(p[i], p[j]);
if (d < min_dist) {
min_dist = d;
}
}
}
return min_dist;
}
double strip_closest(struct point* strip, int size, double d) { // 计算跨越两个部分的点对之间的最小距离
double min_dist = d;
qsort(strip, size, sizeof(struct point), cmp_y);
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size && (strip[j].y - strip[i].y) < min_dist; j++) {
double dist = distance(strip[i], strip[j]);
if (dist < min_dist) {
min_dist = dist;
}
}
}
return min_dist;
}
double closest_util(struct point* px, struct point* py, int n) { // 分治求解
if (n <= 3) { // 当点数小于等于3时,暴力求解
return brute_force(px, n);
}
int mid = n / 2;
struct point mid_point = px[mid];
struct point pyl[mid + 1];
struct point pyr[n - mid - 1];
int li = 0, ri = 0;
for (int i = 0; i < n; i++) { // 将点按照中位数分成两部分
if (py[i].x <= mid_point.x) {
pyl[li++] = py[i];
} else {
pyr[ri++] = py[i];
}
}
double dl = closest_util(px, pyl, mid); // 递归求解左半部分的最小距离
double dr = closest_util(px + mid, pyr, n - mid); // 递归求解右半部分的最小距离
double d = fmin(dl, dr); // 取左右两部分的最小距离
struct point strip[n];
int j = 0;
for (int i = 0; i < n; i++) { // 找到跨越两个部分的点对
if (fabs(py[i].x - mid_point.x) < d) {
strip[j++] = py[i];
}
}
return fmin(d, strip_closest(strip, j, d)); // 取跨越两个部分的点对之间的最小距离
}
double closest(struct point* p, int n) {
struct point px[n];
struct point py[n];
for (int i = 0; i < n; i++) {
px[i] = p[i];
py[i] = p[i];
}
qsort(px, n, sizeof(struct point), cmp_x); // 按x坐标排序
qsort(py, n, sizeof(struct point), cmp_y); // 按y坐标排序
return closest_util(px, py, n); // 分治求解
}
int main() {
int n;
scanf("%d", &n);
struct point p[n];
for (int i = 0; i < n; i++) {
scanf("%lf%lf", &p[i].x, &p[i].y);
}
printf("%.2f\n", closest(p, n));
return 0;
}
```
上述代码中,`cmp_x`和`cmp_y`分别是按x坐标和y坐标进行比较的函数,`distance`用于计算两个点之间的距离,`brute_force`用于暴力求解两个点之间的最小距离,`strip_closest`用于计算跨越两个部分的点对之间的最小距离,`closest_util`递归求解两个部分的最小距离,`closest`是对外的接口函数,用于调用`closest_util`进行分治求解。
阅读全文