一、实验题目

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

二、实验要求

分别用蛮力法和分治法求解最近对问题

  • 输入是平面上的N个点,输出是最近点对距离。
  • 要求随机生成N个点的平面坐标。
  • 分别对N=100,1000,3000,统计算法运行时间(微秒),分析算法的时间性能(提高)。

完成以上实验要求,并给出实验思路和实验总结,并分别给出相应的C语言代码和分别给出N=100,1000,3000的C语言代码内容:

实验思路:

1. 蛮力法:

  1. 遍历集合S中的每一对点,计算它们之间的距离。
  2. 找出距离最小的点对,即为最近点对。

2. 分治法:

  1. 将集合S按照x坐标进行排序。
  2. 将集合S分成两部分,分别为左边的点集L和右边的点集R。
  3. 递归地对点集L和R分别求解最近点对。
  4. 在L和R中分别找出距离最小的点对,记为dL和dR。
  5. 取dL和dR中距离较小的点对,记为d。
  6. 在S中找出以距离d为半径的两个区域内的点对中的最近点对,记为d'.
  7. 返回d和d'中距离较小的点对作为最近点对。

实验总结:

  1. 蛮力法的时间复杂度为O(n^2),需要遍历所有点对进行距离计算。
  2. 分治法的时间复杂度为O(nlogn),将点集分成两部分后递归求解。
  3. 分治法相对于蛮力法在大数据规模下有明显的时间优势。
  4. 通过随机生成n个点的平面坐标,可以对算法的时间性能进行分析和比较。

C语言代码实现:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

typedef struct {
    double x;
    double y;
} Point;

double distance(Point p1, Point p2) {
    double dx = p1.x - p2.x;
    double dy = p1.y - p2.y;
    return sqrt(dx * dx + dy * dy);
}

double bruteForce(Point points[], int n) {
    double minDist = INFINITY;
    for (int i = 0; i < n; i++) {
        for (int j = i+1; j < n; j++) {
            double dist = distance(points[i], points[j]);
            if (dist < minDist) {
                minDist = dist;
            }
        }
    }
    return minDist;
}

double min(double x, double y) {
    return (x < y) ? x : y;
}

double stripClosest(Point strip[], int size, double d) {
    double minDist = d;
    for (int i = 0; i < size; i++) {
        for (int j = i+1; j < size && (strip[j].y - strip[i].y) < minDist; j++) {
            double dist = distance(strip[i], strip[j]);
            if (dist < minDist) {
                minDist = dist;
            }
        }
    }
    return minDist;
}

double closestUtil(Point points[], int n) {
    if (n <= 3) {
        return bruteForce(points, n);
    }
    
    int mid = n / 2;
    Point midPoint = points[mid];
    
    double dl = closestUtil(points, mid);
    double dr = closestUtil(points + mid, n - mid);
    
    double d = min(dl, dr);
    
    Point strip[n];
    int j = 0;
    for (int i = 0; i < n; i++) {
        if (abs(points[i].x - midPoint.x) < d) {
            strip[j] = points[i];
            j++;
        }
    }
    
    return min(d, stripClosest(strip, j, d));
}

double closest(Point points[], int n) {
    qsort(points, n, sizeof(Point), cmpX);
    return closestUtil(points, n);
}

int main() {
    srand(time(NULL));
    int n = 100;  // 或者1000, 3000
    
    Point points[n];
    for (int i = 0; i < n; i++) {
        points[i].x = (double)rand() / RAND_MAX;
        points[i].y = (double)rand() / RAND_MAX;
    }
    
    clock_t start, end;
    double cpu_time_used;
    
    start = clock();
    double minDist = closest(points, n);
    end = clock();
    
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
    
    printf("Minimum distance: %f\n", minDist);
    printf("Time taken: %f seconds\n", cpu_time_used);
    
    return 0;
}
最近点对问题:蛮力法与分治法实现及性能比较

原文地址: https://www.cveoy.top/t/topic/peTV 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录