分治算法解凸包问题

问题

平面点集的凸包问题:给定大量的离散点集合Q,求一个最小的凸多边形,使Q中的点在多边形内或者多边形边上

分治算法

分为以下两步:
1.纵坐标最大的点和纵坐标最小的点连成直线d,将Q分为Q_left和Q_right
2.Deal(Q_left);Deal(Q_right)
Deal(Q_left)的实现过程:
1.以d和距d最远的点p组成三角形,另外两条边记为a和b,点p加入凸包
2.在三角形内的点删除,在边a外侧的点和边a形成新的子问题a_outboard,采用相同的方法处理,在边b外侧的点和边b同样形成新的子问题b_outboard
3.Deal(a_outboard),Deal(b_outboard)

算法分析

找纵坐标最大最小点:O(n)
划分成子问题:O(n)
Deal(Q_left)的复杂度W(n)分析:
找最远的点P:O(n)
根据形成的三角形划分子问题:O(n)
最坏情况下,所有的点(除点p)均在a外侧,
此时W(n)=W(n-1)+O(n),W(3)=O(1)
求得W(n)=O(n^2)

代码实现

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用分治算法决最小问题的 C 语言代码: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define MAX_POINTS 100000 typedef struct point { double x, y; } Point; int compare_x(const void *a, const void *b) { Point *p1 = (Point *)a; Point *p2 = (Point *)b; if (p1->x < p2->x) { return -1; } else if (p1->x > p2->x) { return 1; } else { return 0; } } int compare_y(const void *a, const void *b) { Point *p1 = (Point *)a; Point *p2 = (Point *)b; if (p1->y < p2->y) { return -1; } else if (p1->y > p2->y) { return 1; } else { return 0; } } double dist(Point p1, Point p2) { double dx = p1.x - p2.x; double dy = p1.y - p2.y; return sqrt(dx * dx + dy * dy); } double min(double a, double b) { return a < b ? a : b; } double brute_force(Point points[], int n) { double min_dist = INFINITY; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { double d = dist(points[i], points[j]); if (d < min_dist) { min_dist = d; } } } return min_dist; } double strip_min_dist(Point strip[], int n, double d) { double min_dist = d; qsort(strip, n, sizeof(Point), compare_y); for (int i = 0; i < n; i++) { for (int j = i + 1; j < n && (strip[j].y - strip[i].y) < min_dist; j++) { double d = dist(strip[i], strip[j]); if (d < min_dist) { min_dist = d; } } } return min_dist; } double closest_util(Point points[], int n) { if (n <= 3) { return brute_force(points, n); } int mid = n / 2; Point mid_point = points[mid]; double dl = closest_util(points, mid); double dr = closest_util(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 - mid_point.x) < d) { strip[j] = points[i]; j++; } } return min(d, strip_min_dist(strip, j, d)); } double closest_pair(Point points[], int n) { qsort(points, n, sizeof(Point), compare_x); return closest_util(points, n); } int main() { int n; Point points[MAX_POINTS]; printf("Enter the number of points: "); scanf("%d", &n); printf("Enter the points (x y):\n"); for (int i = 0; i < n; i++) { scanf("%lf %lf", &points[i].x, &points[i].y); } double closest = closest_pair(points, n); printf("The closest pair of points is %lf apart.\n", closest); return 0; } ``` 该代码使用了分治算法决最小问题,其中 `closest_util` 函数实现了分治算法的核心部分,使用了 `brute_force` 函数处理小规模问题,使用了 `strip_min_dist` 函数处理跨越中心线的最小距离。该代码的时间复杂度为 O(nlogn)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值