1.把给定点集中的点在横坐标方向上按照大小排序。如图1所示, p1 p 1 和 pn p n 必是凸多边形的两个顶点。
2.在上凸包点集合 S1 S 1 中找到一个距离直线最远的点 pmax p m a x ,如图2所示。显然直线段 p1 p 1 pmax p m a x 与直线段 pn p n pmax p m a x 把点集 S1 S 1 分成了3个集合。由凸包的性质可知 p1 p 1 , pmax p m a x , pn p n 三点围成的三角形中的点不可能作为凸包的顶点,所以只考虑直线 p1pmax p 1 p m a x 左边的点 S11 S 11 以及直线 pmaxpn p m a x p n 左边的点 S12 S 12 ,如图3所示。
3.递归求解得到凸多边形的边。
4.合并这些点即得所求凸包。
void DealWithLeft(int first, int final, Point *array, Point *result)
{
int max = 0, index = -1;
int i = first;
if (firstarray[final]射线左侧
{
for (i; iint x1 = array[first].x, y1 = array[first].y;
int x2 = array[final].x, y2 = array[final].y;
int x3 = array[i].x, y3 = array[i].y;
int compute = x1*y2 + x3*y1 + x2*y3 - x3*y2 - x2*y1 - x1*y3;
if (compute > max)
{
max = compute;
index = i;
}
}
}
else
{
for (i; i >= 0; i--)//array[final]->array[first]射线左侧
{
int x1 = array[first].x, y1 = array[first].y;
int x2 = array[final].x, y2 = array[final].y;
int x3 = array[i].x, y3 = array[i].y;
int compute = x1*y2 + x3*y1 + x2*y3 - x3*y2 - x2*y1 - x1*y3;
if (compute > max)
{
max = compute;
index = i;
}
}
}
if (index != -1) //取到array[index](即最高点) ,这个点与array[final]、array[first]构成的三角形面积最大
{
Add(array, result, index);
DealWithLeft(first, index, array, result);
DealWithLeft(index, final, array, result);
}
}
快包的效率与快速排序的效率相同,平均情况下是 O(nlog2n) O ( n l o g 2 n ) ,最坏情况下是 O(n2) O ( n 2 ) 。
#include "stdafx.h"
#include
typedef struct {
int x, y;
}Point;
int arrayLength = 0; //数组长度
//初始化测试数据,返回一个数组
void InitialData(Point *array)
{
FILE *fp = freopen("input.txt", "r", stdin);
char ch;
Point* currentPoint = array;
for (int i = 0; ch != EOF; i++)
{
scanf_s("%d%d", &array[i].x, &array[i].y);
ch = fgetc(fp);
arrayLength++;
}
fclose(fp);
}
//交换位置
void swap(Point *array, int i, int j)
{
if (iint x = 0, y = 0;
x = array[i].x;
y = array[i].y;
array[i].x = array[j].x;
array[i].y = array[j].y;
array[j].x = x;
array[j].y = y;
}
}
//返回分裂位置
int Partition(Point *array, int l, int r)
{
int p = l, i = l, j = r + 1;
do
{
do
{
i++;
} while (array[i].x<array[p].x);
do
{
j--;
} while (array[j].x>array[p].x);
swap(array, i, j);
} while (iarray, i, j);
swap(array, p, j);
return j;
}
//按x坐标的值从大到小排序,这里用的是快排
void Qsort(Point *array, int l, int r)
{
int s = 0;
if (larray, l, r); //找到分裂位置
Qsort(array, l, s - 1);
Qsort(array, s + 1, r);
}
}
//打印数组
void Put(Point *array, int length)
{
for (int i = 0; i"%d\t%d\n", array[i].x, array[i].y);
}
printf_s("\n");
}
int resultCount = 0; //result[15]里面插入值的个数
//向result数组里面添加array数组首尾项
void Add(Point *array, Point *result)
{
result[resultCount].x = array[0].x;
result[resultCount++].y = array[0].y;
result[resultCount].x = array[14].x;
result[resultCount++].y = array[14].y;
}
//向result数组里面添加 array[i]
void Add(Point *array, Point *result, int i)
{
result[resultCount].x = array[i].x;
result[resultCount++].y = array[i].y;
}
//处理array[first]->array[final]射线左侧的点
void DealWithLeft(int first, int final, Point *array, Point *result)
{
int max = 0, index = -1;
int i = first;
if (first//array[first]->array[final]射线左侧
{
for (i; iint x1 = array[first].x, y1 = array[first].y;
int x2 = array[final].x, y2 = array[final].y;
int x3 = array[i].x, y3 = array[i].y;
int compute = x1*y2 + x3*y1 + x2*y3 - x3*y2 - x2*y1 - x1*y3;
if (compute > max)
{
max = compute;
index = i;
}
}
}
else
{
for (i; i >= 0; i--)//array[final]->array[first]射线左侧
{
int x1 = array[first].x, y1 = array[first].y;
int x2 = array[final].x, y2 = array[final].y;
int x3 = array[i].x, y3 = array[i].y;
int compute = x1*y2 + x3*y1 + x2*y3 - x3*y2 - x2*y1 - x1*y3;
if (compute > max)
{
max = compute;
index = i;
}
}
}
if (index != -1) //取到array[index](即最高点) ,这个点与array[final]、array[first]构成的三角形面积最大
{
Add(array, result, index);
DealWithLeft(first, index, array, result);
DealWithLeft(index, final, array, result);
}
}
void GetResult(Point *array, Point *result)
{
Add(array, result); //将首尾两个点并入result[15]
DealWithLeft(0, 14, array, result); //处理array[0]->array[14]射线左边的点
DealWithLeft(14, 0, array, result); //处理array[14]->array[0]射线右边的点
}
int _tmain(int argc, _TCHAR* argv[])
{
Point array[15], result[15];
//初始化数组数据
InitialData(array);
printf_s("输入数据:\n\n");
Put(array, arrayLength);
//给数组排序,按x从小到大
Qsort(array, 0, arrayLength - 1);
printf_s("排序后的数据:\n\n");
Put(array, arrayLength);
//获取result数组,存放所有结果顶点
GetResult(array, result);
printf_s("结果集:\n\n");
Put(result, resultCount);
getchar();
return 0;
}