c语言凸包算法,基于C语言的凸包算法实现

基于C语言的凸包算法实现

非计算机专业,代码有些的不好的地方,大佬轻喷^ _ ^

根据要求,需要使用C语言实现凸包算法——Graham扫描法,本文将从算法理解、实现思路、遇到的问题及其解决方案三个方面来阐述实现过程。

算法理解

凸包算法Graham扫描法,在不考虑排序算法的时间复杂度情况下,算法核心程序的时间复杂度为 O ( n l o g n ) O(n log n)O(nlogn),其主要算法思想如下:

首先是预处理过程,获得一组随机点集,选取位于二维空间中左下角的点,即在纵坐标(y)最小情况下横坐标(x)为最小的点P 0 P_0P0​ 。以该点位极坐标原点计算其余各点的极角θ \thetaθ,并根据极角大小进行升序排序,若极角相同则按极径大小按升序排列。由此得到一组按照极角排序的点集 { P 0 , P 1 , . . . , P n } \left\{P_0,P_1,...,P_n\right\}{P0​,P1​,...,Pn​}(如下图所示)。

6c1555302777729326ca3efa0910d9ec.png

完成预处理之后即Graham算法的核心步骤,主要通过栈的方式来实现凸包点的计算。首先将P 0 , P 1 P_0,P_1P0​,P1​两点压栈,他们必然属于凸包上的点。然后进入迭代过程,以栈顶元素A [ t o p ] A[top]A[top]和次栈顶元素 A [ t o p − 1 ] A[top-1]A[top−1]构成的向量a ⃗ \vec{a}a为基准计算其与当前P k P_kPk​点与栈顶元素A [ t o p ] A[top]A[top]构成的向量b ⃗ \vec{b}b的叉积 ,若结果为正(零)则 b ⃗ \vec{b}b 位于 a ⃗ \vec{a}a 的逆时针方向(共线),P k P_kPk​进栈 ,若结果为负则 b ⃗ \vec{b}b 位于 a ⃗ \vec{a}a 的顺时针方向, A [ t o p ] A[top]A[top]出栈, P k P_kPk​进栈,直至扫描至最后一个点,将 P 0 P_0P0​ 再次进栈是凸包闭合。

由于要求顺时针输出凸包顶点,则将栈中元素从栈顶向栈底依次输出即可。

实现思路及过程

根据Graham扫描法的算法理解,将程序实现分为了随机点坐标初始化、极角计算及排序、Graham核心算法和结果输出四个模块共计8个函数进行编码实现。

结构体定义

// 点坐标

typedef struct POINT {

int x;

int y;

}Point;

坐标初始化

首先构造存储点坐标的结构体Point,该结构体中仅包含横坐标x和纵坐标y。根据要求需要随机生成100个点,使用宏定义点集大小(SIZE)为100。使用库下的rand()函数以当前系统时间为种子生成 0 ≤ x < 50 , 0 ≤ y < 50 0\le x<50,0\le y<500≤x<50,0≤y<50 的点,并依次存入大小为SIZE的Point的类型的一维数组中。

void InitPoint(Point* p) {

int i;

srand(time(0));

for (i = 0; i < SIZE; i++) {

(p + i)->x = (int)(rand() % 50);

(p + i)->y = (int)(rand() % 50);

}

}

极角计算及排序

首先选取点集中位于左下角的点,采用的方法为先找出纵坐标 最小的坐标点(集),然后在其中找出横坐标 最小的坐标点,记录该点位于原始点集的位置,将其与第一个点进行交换。接着使用库下的atan()函数计算各点的极角,并将其记录在double类型大小为SIZE的一维数组angle中,令极坐标原点的极角: a n g l e [ 0 ] = 0 angle[0] = 0angle[0]=0。使用冒泡排序算法对极角进行排序,同时改变点集中各点的顺序。在排序是要考虑当极角相同时按极径从小到大排序。

Graham核心算法

根据算法分析结果,定义一个Point类型的一维数组作为栈空间,定义栈顶定位变量top,用于标记栈顶元素在栈中的位置,定义临时变量temp_point用记录当前扫描到的坐标点,定义叉积计算函数,返回值为布尔类型。当叉积为非负时返回true,否则返回false。判断temp_point和栈顶元素,次顶元素三个点组成的两个向量的方向,若叉积返回值为正,则将temp_point进栈,否则将当前栈顶元素出栈,继续判断现在的栈顶元素和次顶元素与temp_point三个点的向量叉积……

得到包含所有凸包顶点的栈数组,最后将 点进栈形成封闭凸包,在形成封闭凸包前需要对 以及当前栈顶和次顶元素进行判断是否符合凸包结构,若符合则将 进栈,反之将当前栈顶元素出栈,重复判断步骤直至符合为止。

int myGraham(Point* p, Point* p_stack) {

int top = -1; //栈顶指针

int p_index = 0; //点索引

Point temp_point;

top++; p_stack[top] = p[0]; p_index++; //push

top++; p_stack[top] = p[1]; p_index++; //push

while (p_index < SIZE) {

temp_point = p[p_index];

if (X(p_stack[top - 1], p_stack[top], temp_point))

{

top++; p_stack[top] = temp_point;//push

}

else {

top--;//pop

continue;

}

p_index++;

}

while (TRUE) {

if (!X(p_stack[top - 1], p_stack[top], p[0])) {

top--;

}

else {

break;

}

}

top++; p_stack[top] = p[0];

return top;

}

结果输出

为了使结果更直观,定义了一个输出函数,能够输出凸包顶点坐标,并在二维坐标中,显示点。

运行结果

6c1555302777729326ca3efa0910d9ec.png

6c1555302777729326ca3efa0910d9ec.png

6c1555302777729326ca3efa0910d9ec.png

来源:oschina

链接:https://my.oschina.net/u/4355012/blog/4274913

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429684.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VS Code 使用小技巧

所有插件查找地址&#xff08;https://marketplace.visualstudio.com/&#xff09; 编码快捷方式&#xff08;http://docs.emmet.io/cheat-sheet/&#xff09; 安装插件出现 错误unable to verify the first certificate &#xff08;无法确认第一证书&#xff09;   解决方…

android 怎么自定义任务栈,Android中的Activity详解--启动模式与任务栈

目录Activity生命周期任务栈启动模式Intent FlagtaskAffinity属性1.Activityactivity的简单介绍就不写了&#xff0c;作为最常用的四大组件之一&#xff0c;肯定都很熟悉其基本用法了。2.生命周期首先&#xff0c;是都很熟悉的一张图&#xff0c;即官方介绍的Activity生命周期图…

SQL Server--疑难杂症之坑爹的Windows故障转移群集

-- 估计是春节前最后一次写博客&#xff0c;也估计是本年值班最后一次踩雷&#xff0c;感叹下成也SQL SERVER&#xff0c;败也SQL SERVER。 -- 场景描述&#xff1a; 操作系统版本 &#xff1a;Windows Server 2012 数据中心版本 数据库版本 &#xff1a;SQL SERVER 2012 企业版…

android handle 阻塞,Android全面解析之Handler机制:常见问题汇总

主线程为什么不用初始化Looper&#xff1f;答&#xff1a;因为应用在启动的过程中就已经初始化主线程Looper了。每个java应用程序都是有一个main方法入口&#xff0c;Android是基于Java的程序也不例外。Android程序的入口在ActivityThread的main方法中&#xff1a;// 初始化主线…

UML中的6大关系(关联、依赖、聚合、组合、泛化、实现)

UML定义的关系主要有六种&#xff1a;依赖、类属、关联、实现、聚合和组合。这些类间关系的理解和使用是掌握和应用UML的关键&#xff0c;而也就是这几种关系&#xff0c;往往会让初学者迷惑。这里给出这六种主要UML关系的说明和类图描述&#xff0c;一看之下&#xff0c;清晰明…

性能调优-硬盘方面,操作系统方面,文件系统方面

硬盘对数据库性能的影响 传统机械硬盘 当前大多数数据库使用的都是传统的机械硬盘。机械硬盘的技术目前已非常成熟&#xff0c;在服务器领域一般使用SAS或SATA接口的硬盘。服务器机械硬盘开始向小型化转型&#xff0c;目前已经有大量2.5寸的SAS机械硬盘。 机械硬盘有两个重要的…

chrome Android 80,Chrome OS 80将为Chromebook带来侧载Android应用的支持

如需体验这项功能&#xff0c;需在启动 Crostini 容器时加上一行特殊的命令 —— 从 Chromebook 命令行启动时&#xff0c;请加上 –enable-features ArcAdbSideloading 。最终&#xff0c;我们希望这回成为一项明示的标记(flags)功能。如变更日志所述&#xff0c;用户可通过托…

android 日历仿IOS,基于Android week view仿小米和iphone日历效果

前言最近由于项目需求&#xff0c;要做一个仿小米日历的功能&#xff0c;下面显示一天的日程&#xff0c;header以周为单位进行滑动&#xff0c;github上找了很久也没有找到合适的&#xff0c;但找到一相近的开源项目Android-week-view&#xff0c;它不是我们项目所需要的效果&…

1、管理员登录中间件和注销

1、根据session去判断用户是否登录&#xff0c;登录后才可以进index首页&#xff0c;否则返回login页面&#xff0c;借助中间件 (1)修改路由 Route::group([middleware > [web,admin.login],prefix>admin,namespace>Admin], function () { //注册一个中间件admin.logi…

HTML阅读打开点击不了,如何让网页文章中的代码可以点击运行

在网页中运行代码HTML5学堂&#xff1a;很多代码网站当中&#xff0c;都会提供运行代码段功能&#xff0c;便于查看代码效果&#xff0c;那么这个是如何实现的呢&#xff1f;一起来看一下——如何在网页中运行代码。HTML5学堂-刘国利said&#xff1a;应该是在2013年的时候&…

html留言回复评论页面模板,HTML5实现留言和回复的页面样式

这篇文章主要介绍了用HTML5如何实现留言和回复样式,需要的朋友可以参考下具体就不做详细讲解了&#xff0c;直接上代码&#xff1a;web开发-webkfa.com*{margin:0;padding:0;-webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */-webkit-t…

html5列表菜单特效,HTML5 SVG汉堡包菜单按钮分段动画特效

这是一款效果非常炫酷的HTML5 SVG汉堡包菜单按钮分段动画特效。该菜单按钮特效在用户点击汉堡包按钮时&#xff0c;按钮会分割为多段&#xff0c;并旋转变形为关闭按钮的状态。当再次点击该按钮时&#xff0c;它会逆向变形为汉堡包图标。该特效是基于Segment.js插件(一款可以只…

计算机选修课学什么,计算机专业都学什么 主要课程有什么

计算机专业的主要学习内容有什么呢&#xff0c;都开设哪些课程呢&#xff0c;下面小编为大家提供计算机专业主要学习内容&#xff0c;仅供大家参考。计算机专业主要学习内容一、数学类主要课程&#xff1a;高等数学、线性代数、离散数学、概率论、数理统计二、语言类主要课程&a…

excel取html文本长度,excel字符长度 怎么计算excel里的字符串的长度

请教&#xff1a;在EXCEL中如何统计字符长度&#xff1f;打开excel文件&#xff0c;确定需要编辑的内容选择功能区的“公式”功能在公式中选择“LEN”功能在text中选择需要编辑的单元格 7、点击“确定” 8、系统自动计算出了单元excel中怎么判断字符串的长度在Excel中可以使用两…

Java虚拟机(JVM)默认字符集详解

Java中对字符串等进行转换字节数组时, 需要根据字符集编码来进行转换, 当不显示的指定字符集编码时(如: "测试".getBytes()), 会使用Charset.defaultCharset()获取到的字符集编码进行转换! 相关代码如下: 上面的代码可以看出, 在JVM中defaultCharset()是在初始化阶段…

计算机本地用户删除后怎么恢复,Default User文件夹被删了怎样恢复

满意答案opposities2013.06.06采纳率&#xff1a;80% 等级&#xff1a;24已帮助&#xff1a;17327人1、开机后出现“Windows 不能加载本地存储的配置文件。此问题的可能原因是安全权限不足或本地配置文件损坏。如果此问题持续存在&#xff0c;请与您的网络管理员联系。倒数3…

08-SSH综合案例:前台用户模块:注册页面的前台JS校验

这个是MyEclipse设置的问题 把设置去掉就没问题了。 你也可以在每一个input后面加个span来显示提示的信息。这些东西也要提交到后台&#xff0c;后台也是要对这些东西进行校验的。转载于:https://www.cnblogs.com/ZHONGZHENHUA/p/6377756.html

计算机管理员无法创建密码,找到电脑管理员的密码

轻松找回遗忘的WinXP管理员密码很多“不拘小节”的朋友在使用电脑时&#xff0c;经常是昨天改了Windows XP帐户密码&#xff0c;今天便忘记了内容&#xff0c;把自己锁在“门外”的情况时有发生。对此&#xff0c;大多数朋友只能痛苦的去重新安装系统。其实如果你有以下的条件&…

clientWidth、clientHeight、offsetWidth、offsetHeight以及scrollWidth、scrollHeight

clientWidth、clientHeight、offsetWidth、offsetHeight以及scrollWidth、scrollHeight是几个困惑了好久的元素属性&#xff0c;趁着有时间整理一下 1. clientWidth 和 clientHeight 网页中的每个元素都具有 clientWidth 和 clientHeight 属性&#xff0c;表示可视区域的宽高&…

API文档工具-Swagger的集成

最近安装了API文档工具swagger&#xff0c;因为Github上已有详细安装教程&#xff0c;且安装过程中没有碰到大的阻碍&#xff0c;所以此文仅对这次安装做一份大致记录 相关网站 Swagger 官方地址&#xff1a;http://swagger.wordnik.com Github安装详解【springmvc集成swagger】…