#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <math.h>
坐标数据结构:
typedef struct
{
float x;
float y;
}Point;
typedef bool(*Func)(Point, Point, Point);
判断点test是否在a,b组成的直线的上方:
bool Upstair(Point a, Point b, Point test)
{
double k, d;
if (fabs(a.x - test.x) < 0.000001 && fabs(a.y - test.y) < 0.000001
|| fabs(b.x - test.x) < 0.000001 && fabs(b.y - test.y) < 0.000001)
return false;
/* 此时test点肯定不符合结果(联想在main函数寻找a,b点时的要求) */
if (fabs(b.x - a.x) < 0.000001)
return false;
k = (b.y - a.y) / (b.x - a.x);
d = a.y - k * a.x;
double ret = k*test.x - test.y + d;
if (ret < -0.000001) //点在上方
return true;
else //点在线上 和 点在线的下方
return false;
}
判断点test是否在a,b组成的直线的下方:
bool Downstair(Point a, Point b, Point test)
{
double k, d;
if (fabs(a.x - test.x) < 0.000001 && fabs(a.y - test.y) < 0.000001
|| fabs(b.x - test.x) < 0.000001 && fabs(b.y - test.y) < 0.000001)
return false;
/* 此时test点肯定不符合结果(联想在main函数寻找a,b点时的要求) */
if (fabs(b.x - a.x) < 0.000001)
return false;
k = (b.y - a.y) / (b.x - a.x);
d = a.y - k * a.x;
double ret = k*test.x - test.y + d;
if (ret > 0.000001) //点在下方
return true;
else //点在线上 和 点在线的上方
return false;
}
查找符合的点,递归函数:
void FindPoint(Point point[], int plen, Point a, Point b, Func func)
{
if (plen == 0)
return;
/* 找出 Pmax 点 */
Point pmax;
pmax.x = point[0].x;
pmax.y = point[0].y;
double k, d;
k = (b.y - a.y) / (b.x - a.x);
d = a.y - k * a.x;
double dist = fabs(k*pmax.x - pmax.y + d);
double newdist;
for (int i = 1; i < plen; ++i)
{
newdist = fabs(k*point[i].x - point[i].y + d);
if (newdist - dist > 0.000001)
{
pmax.x = point[i].x;
pmax.y = point[i].y;
}
else if (fabs(newdist - dist) < 0.000001)
{ //选择使角PmaxPaPb最大的点
double k_pmax = (pmax.y - a.y) / (pmax.x - a.x);
double k_point = (point[i].y - a.y) / (point[i].x - a.x);
if (fabs(k_point - k) - fabs(k_pmax - k) > 0.000001)
{
pmax.x = point[i].x;
pmax.y = point[i].y;
}
}
}
printf("Point(%f, %f)\n", pmax.x, pmax.y);
/* 找出各自符合满足 Pmax,Pa 和 Pmax,Pb 的点 */
Point *p1 = (Point *)malloc((plen / 2 + 1)*sizeof(Point));
Point *p2 = (Point *)malloc((plen / 2 + 1)*sizeof(Point));
int p1idx = 0, p2idx = 0;
for (int i = 0; i < plen; ++i)
{
if (func(pmax, a, point[i]))
{
p1[p1idx].x = point[i].x;
p1[p1idx].y = point[i].y;
p1idx++;
}
else if (func(pmax, b, point[i]))
{
p2[p2idx].x = point[i].x;
p2[p2idx].y = point[i].y;
p2idx++;
}
}
/* 递归寻找Pmax */
FindPoint(p1, p1idx, pmax, a, func);
FindPoint(p2, p2idx, pmax, b, func);
free(p1);
free(p2);
}主函数:
int _tmain(int argc, _TCHAR* argv[])
{
int number = 0;
while (number < 3)
{
printf("How much Point do you input(>=3):\n");
scanf("%d", &number);
}
printf("Please input Point:\n");
Point *p = (Point *)malloc(number * sizeof(Point));
for (int i = 0; i < number; ++i)
{
scanf("%f%f", &(p[i].x), &(p[i].y));
}
/* 找出两个顶点 */
Point a, b;
a.x = p[0].x;
a.y = p[0].y;
b.x = p[0].x;
b.y = p[0].y;
for (int i = 1; i < number; ++i)
{
if (a.x - p[i].x > 0.000001) //有比a更小的(横坐标)
{
a.x = p[i].x;
a.y = p[i].y;
}
else if (fabs(a.x - p[i].x) < 0.000001)
{ // 存在和a在同一竖直线上的点,此时应该选择最上或最下的点(这里选最上)
if (p[i].y - a.y > 0.000001)
{
a.x = p[i].x;
a.y = p[i].y;
}
}
if (b.x - p[i].x < -0.000001)
{
printf("b change\n");
b.x = p[i].x;
b.y = p[i].y;
}
else if (fabs(b.x - p[i].x) < 0.000001)
{ // 存在和b在同一竖直线上的点,此时应该选择最上或最下的点(这里选最下,和a对应,为了更可能的均分上包和下包点数)
if (p[i].y - a.y < -0.000001)
{
b.x = p[i].x;
b.y = p[i].y;
}
}
}
/* 所有点在一条竖直的线,则此时已是所求结果 */
if (fabs(a.x - b.x) < 0.000001)
{
printf("Point(%f, %f)\n", a.x, a.y);
printf("Point(%f, %f)\n", b.x, b.y);
system("pause");
return 0;
}
printf("Point(%f, %f)\n", a.x, a.y);
printf("Point(%f, %f)\n", b.x, b.y);
/* 划分点为两个集,即上包 和 下包*/
Point *p1 = (Point *)malloc((number / 2 + 1)*sizeof(Point));
Point *p2 = (Point *)malloc((number / 2 + 1)*sizeof(Point));
int p1idx = 0, p2idx = 0;
for (int i = 0; i < number; ++i)
{
if (Upstair(a, b, p[i]))
{
p1[p1idx].x = p[i].x;
p1[p1idx].y = p[i].y;
p1idx++;
}
else if (Downstair(a, b, p[i]))
{
p2[p2idx].x = p[i].x;
p2[p2idx].y = p[i].y;
p2idx++;
}
}
FindPoint(p1, p1idx, a, b, Upstair);
FindPoint(p2, p2idx, a, b, Downstair);
free(p);
free(p1);
free(p2);
system("pause");
_tmain(0, NULL);
return 0;
算法分析:
在输入数中分上包和下包时时间复杂度为O(n),两个递归函数的调用规模下降为n/2.
故可得T(n) = 2T(n/2) + n,递归函数遍历元素时间复杂度为n,然后同样道理递归, 最好的效率是刚好上包和下包元素相等或差一的情况。
由T(n) = 2T(n/2) + n ,得T(2^k) = 2T(2^k-1) + 2^k
T(2^k) = 2(2T(2^k-2) + 2^k-1) + 2^k
= 2^2T(2^k-2) + 2*2^k
= 2^kT(1) + k*2^k
由T(1) = 1,k = logn
T(n) = n + logn*n
所以,时间复杂度是nlogn.
今天的文章【算法学习】快包算法分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/62672.html