果园篱笆c语言算法,凸包问题(果园篱笆)

#include

#include

定义存储struct Point //点坐标的结构

举止

PS x;

int y;

}

因为在struct Dj //算法执行中把中间过程的点的集合存储在链表中,所以在此定义具有另一个后续指针的点坐标的构造体。

举止

PS x;

int y;

struct Dj* next;

}

struct Dj Phead; //最终将凸包的各顶点保存在一个链表中,在此定义该链表的开头节点

结构DJ pend; //上述链表的末尾节点

void fz(struct Point pmin,struct Point pmax,struct Dj* P) //分治法的反复算法函数,三个参数分别是线段的两个端点和应判断的点的集合

举止

PK (PS!=NULL) //判断点集是否为空

举止

int mid=0; //定义点距线段的最远距离

struct Dj* no; //定义存储要处理的点的集合

结构点pmid; //定义最远的点

pmid.x=(*P).x; pmid.y=(*P).y; //初始化最远的点

struct Dj* Pl=NULL,* Pr=NULL; //初始化以下迭代的两个点集

struct Dj* Pln=NULL,* Prn=NULL; //初始化存储下一次迭代的两个点集的当前位置

mid=-((pmax.y-pmin.y ) * pmid.x-(pmax.x-pmin.x ) * pmid.y-pmax.y * pmin.y * pmax.x; //从初始化点到线段的最远距离

no=(*P).next; //初始化存储要处理点的集合

int n=1;

PS (否!=NULL) //更新最远距离和最远距离的点

举止

n;

if (-((pmax.y-pmin.y ) * (* no ).x-(pmax.x-pmin.x ) * (* no ).y-pmax.y * pmin.y * pmax.x ) mid )

举止

mid=-((pmax.y-pmin.y ) * (* no ).x-(pmax.x-pmin.x ) * (* no ).y-pmax.y * pmin.y * pmax.x );

pmid.x=(*否).x; pmid.y=(*否).y;

以下

no=(*no).next;

以下

打印(' % s % d % s % s % s ','('、' pmid.x,'、'、pmid.y,')','; //输出最远距离的点

no=P;

struct Dj no1[50];

int i=0;

PS (否!=NULL) //将最远距离点的两侧的点分别放入点集中

举止

no1[i]=*no;

no1[i].next=NULL;

if ((pmid.y-pmin.y ) * no1 [ I ].x-(pmid.x-pmin.x ) * no1 [ I ].y-pmid.y * pmin.y * pmid.x0 )//在直线方程式的判定位置上带点

举止

PS (K==null )

{Pl=(no1[i] ); Pln=(no1[i] ); 以下

else

{(*Pln).next=(no1[i] ); 以下

以下

else if ((pmax.y-pmid.y ) * no1 [ I ].x-(pmax.x-pmid.x ) * no1 [ I ].y-pmax.y * pmid.x * pmid.y * pmax.x0 )//将点带入直线方程式的判定位置

举止

PS (PS==null )

{Pr=(no1[i] ); Prn=(no1[i] ); 以下

else

{(*Prn).next=(no1[i] ); 以下

以下

no=(*no).next;

I;

以下

重复以fz(pmin,pmid,Pl) //原始线段的左侧点和最远的距离点为线段的两个端点和左侧点集

用线段的两个端点和右侧点集重复fz(pmid,pmax,Pr) //最远的距离点和原始线段的右侧点

以下

}

void main ()

举止

PS;

printf ('请输入点数: ' );

扫描(' % d ',n );

printf ('请输入各点: ' );

结构点a [ 50 ]; //定义大的数组,保证能安装所有的点

int i=0;

for(i=1; i=n; 依次输入i ) //点

举止

扫描(' % d ',a[i-1].x );

扫描(' % d ',a[i-1].y );

以下

结构点pmax=a[0],pmax=a[0];

for(i=1; ipmax.x )

pmax=a[i];

以下

Phead.x=pmin.x; Phead.y=pmin.y; Phead.next=NULL;

Pend.x=pmax.x; Pend.y=pmax.y; Pend.next=NULL; //把横轴的最大和最小的点放在最终的链表中

Phead.next=Pend;

struct Dj* Pup=NULL,* Pdown=NULL;

struct Dj* Pupn=NULL,* Pdownn=NULL; //初始化横轴的最大和最小点构成线段的上侧和下侧两个点集

struct Dj mid[50];

for(i=0; i0) //向下方的点集添加点

举止

if (Pdown==NULL )

举止

Pdown=(mid[i] );

PDO WNN=(PS [ I ] );

以下

else

{(*Pdownn).next=(mid[i] );

PDO WNN=(PS [ I ] ); 以下

以下

以下

printf ('构成凸包的顶点分别为: ' );

打印(' % s % d % s % s % s ',' ('.pmin.x,',',pmin.y,')',';

打印(' % s % d % s % s % s ','('、pmax.x,'、pmax.y,')','; //输出横轴的最大和最小的点

fz(pmin、pmax、Pup )

使用fz(pmax、pmin、Pdown) //分数函数处理上侧和下侧两个点集

系统(' pause ' );

以下

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用C语言解决凸包问题并实现可视化动态效果,可以使用以下步骤: 1. 首先,需要使用凸包算法来计算给定点集的凸包。常见的凸包算法有Graham扫描算法和Jarvis步进算法。 2. 在计算凸包时,需要使用一个数据结构来存储点的坐标信息。可以使用C语言中的结构体来表示点,如下所示: ``` typedef struct { double x; double y; } Point; ``` 3. 在计算凸包时,需要将点按照一定的顺序进行排序。可以使用C语言中的qsort函数来实现,如下所示: ``` int cmp(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; } } qsort(points, n, sizeof(Point), cmp); ``` 4. 在计算凸包时,需要将点按照一定的顺序进行连接。可以使用C语言中的图形库来实现可视化效果,如下所示: ``` void drawLine(Point p1, Point p2) { line(p1.x, p1.y, p2.x, p2.y); delay(100); } for (int i = 0; i < hullSize - 1; i++) { drawLine(hull[i], hull[i+1]); } drawLine(hull[hullSize-1], hull[0]); ``` 这里使用了一个自定义的drawLine函数来绘制线段,并使用了delay函数来实现动态效果。 完整的C语言实现代码如下所示: ``` #include <stdio.h> #include <stdlib.h> #include <graphics.h> #include <math.h> #define MAX_POINTS 1000 typedef struct { double x; double y; } Point; int cmp(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; } } double crossProduct(Point p1, Point p2, Point p3) { double x1 = p2.x - p1.x; double y1 = p2.y - p1.y; double x2 = p3.x - p2.x; double y2 = p3.y - p2.y; return x1 * y2 - x2 * y1; } void drawLine(Point p1, Point p2) { line(p1.x, p1.y, p2.x, p2.y); delay(100); } int main() { int gd = DETECT, gm; initgraph(&gd, &gm, ""); Point points[MAX_POINTS]; int n = 0; while (!kbhit() && n < MAX_POINTS) { if (ismouseclick(WM_LBUTTONDOWN)) { clearmouseclick(WM_LBUTTONDOWN); int x = mousex(); int y = mousey(); points[n].x = x; points[n].y = y; n++; putpixel(x, y, WHITE); } } qsort(points, n, sizeof(Point), cmp); Point hull[MAX_POINTS]; int hullSize = 0; for (int i = 0; i < n; i++) { while (hullSize >= 2 && crossProduct(hull[hullSize-2], hull[hullSize-1], points[i]) <= 0) { hullSize--; } hull[hullSize] = points[i]; hullSize++; } int hullStart = 0; for (int i = n - 2; i >= 0; i--) { while (hullSize >= hullStart + 2 && crossProduct(hull[hullSize-2], hull[hullSize-1], points[i]) <= 0) { hullSize--; } hull[hullSize] = points[i]; hullSize++; } for (int i = 0; i < hullSize - 1; i++) { drawLine(hull[i], hull[i+1]); } drawLine(hull[hullSize-1], hull[0]); getch(); closegraph(); return 0; } ``` 在运行程序时,可以使用鼠标点击来添加点,程序会自动计算凸包并进行可视化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值