清华计算几何-算法LowBound和ConvexHull(凸包)-GrahamScan

算法复杂度最低界限LowBound

算法求解复杂度是否存在一个最低界限,有时候想尽一切办法优化一个算法,去优化其复杂度,比如

清华计算几何-ConvexHull(凸包)-求极点InTriangle/ToLeft Test-CSDN博客

清华计算几何-ConvexHull(凸包)-求极边_计算几何中的toleft测试-CSDN博客

清华计算几何-ConvexHull(凸包)-JarivsMarch-CSDN博客

算法复杂度依次到: O(n4), O(n3), O(n2)

一直优化下去能最低到哪个复杂度,有时候不好直接估算出。有个比较好的办法是从经典算法(比如排序)中,找到此算法和经典算法的等价转换。如果此算法和经典算法等价,则此算法的LowBound也是经典算法的LowBound。

算法等价转换

算法等价转换就是: 假设A为经典算法, 已经知道其算法复杂度。存在另外一个未知算法复杂度的算法B,如今要估算算法B的lowBond.  如果A算法的输入经过O(n)以内复杂度转换算法变为B算法输入,B算法计算的输出能在O(n)复杂度以内转换为A算法的输入,则称A算法和B算法等价。

估算ConvexHull算法的LowBound

从前面可以隐隐看出点集求解ConvexHull的流程和排序类似, 建立起排序和凸包的点集合之间O(n)的转换关系(点输入和点输出),排序的算法Lowbound就是凸包算法的Lowbound。

排序的LowBound是O(nlogn), 而等价下凸包算法也是O(nlogn)

 

凸包算法-GrahamScan

GrahamScan算法流程

 Presorting(预排序)

[1]找到LowertToLeft点P

[2]找到和P点相连最右边的点(逆时针CCW)

 Scan(扫描)

GrahamScan算法Backtrack执行案例

GrahamScan算法代码实现

算法核心代码

#include <iostream>
#include <vector>
#include <stack>
#include <list>
#include <algorithm>#include "BasicCompute.h"using namespace std;template<typename type>
class CustomStack
{
private:vector<type> datas;public:CustomStack(){}void Push(const type& value){datas.push_back(value);}type Pop(){int num = GetNum();if (num == 0)throw "size is zero, do not allow pop";int value = datas[num - 1];datas.pop_back();return value;}int GetNum(){return datas.size();}type GetTopValue(int topIndex = 0){return datas[GetNum() - topIndex - 1];}void GetVectorData(vector<type>& outDatas){outDatas = datas;}
};void GrahamScan_GetConvexPointSet(const vector<Point>& inPoints, vector<int>& convecHullPointIndexs)
{if (inPoints.size() <= 3)return;convecHullPointIndexs.empty();int ltfIndex = FindLowestThenLeftmost(inPoints);// quick sort by to leftvector<int> tArray;for (int index = 0; index < inPoints.size(); index++){if (index != ltfIndex)tArray.push_back(index);}auto CompareFunc = [&](int a, int b){return IsLeft(inPoints[ltfIndex], inPoints[a], inPoints[b]);};sort(tArray.begin(), tArray.end(), CompareFunc);// init stack s and stack tCustomStack<int> s;s.Push(ltfIndex);s.Push(tArray[0]);CustomStack<int> t;for (int index = tArray.size() - 1; index >= 1; index--){t.Push(tArray[index]);}while (t.GetNum() != 0){int sTopIndex = s.GetTopValue(0);int sTopSecondIndex = s.GetTopValue(1);int tTopIndex = t.GetTopValue(0);if (IsLeft(inPoints[sTopSecondIndex], inPoints[sTopIndex], inPoints[tTopIndex])){s.Push(t.Pop());}else{s.Pop();}}s.GetVectorData(convecHullPointIndexs);
}

测试代码


#include <iostream>
#include <vector>
#include "ExtremityEdgeConvex.h"
#include "JarvisMarch.h"
#include "GrahamScan.h"using namespace std;int main()
{std::cout << "Hello World!\n";// point set contructvector<Point> inPoints ={{0, 0},{-1, -1},{5, 2},{4, 5},{3, 3},{-1, 3},{2, 2},{-3, 2},};vector<int> convecHullPointIndexs;GrahamScan_GetConvexPointSet(inPoints, convecHullPointIndexs);for (int index = 0; index < convecHullPointIndexs.size(); index++){int pointIndex = convecHullPointIndexs[index];printf("(%f, %f)\n", inPoints[pointIndex].x, inPoints[pointIndex].y);}
}

测试结果

GrahamScan算法复杂度

PreProcesing:LTL复杂度O(n), Presorting是快排O(nlogn)

San扫描: Scan经过的路径是一个平面图(PlanarGraph), N个顶点的平面图至多拥有3N条边,也就是San算法复杂度不可能超过3N。也就是算法复杂度为O(n).

综上GrahamScan算法复杂度为O(nlogn)。

参考资料

[1]清华计算几何 P31-P48

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

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

相关文章

DeFi革命:揭秘去中心化金融的核心技术与实操指南

目录 DeFi&#xff08;去中心化金融&#xff09;综述 基本特点 第一&#xff0c;DeFi 是无许可的金融 第二&#xff0c;DeFi 是无门槛的金融 第三&#xff0c;DeFi 是无人驾驶的金融 典型商业模式 闪电贷 MakerDAO 面临的挑战 DeFi技术要点 椭圆曲线签名 EIP-712:…

模拟依赖关系和 AI 是Vue.js测试的下一个前沿领域

Vue.js 是一个流行的 JavaScript 框架&#xff0c;因此&#xff0c;确保其组件按预期工作至关重要&#xff1a;有效&#xff0c;更重要的是&#xff0c;可靠。模拟依赖项是最有效的测试方法之一&#xff0c;我们将在本文中发现。 模拟依赖项的必要性 模拟依赖项是一种对测试施加…

个人定制化形象生成,FaceChain最新模型部署

FaceChain是阿里巴巴达摩院推出的一个开源的人物写真和个人数字形象的AI生成框架。 FaceChain利用了Stable Diffusion模型的文生图功能&#xff0c;并结合人像风格化LoRA模型训练及人脸相关感知理解模型&#xff0c;将输入的图片进行训练后推理输出生成个人写真图像。 FaceCh…

基于深度学习的文本自监督学习

基于深度学习的文本自监督学习&#xff08;Self-Supervised Learning, SSL&#xff09;是一种利用未标注文本数据通过预任务进行训练&#xff0c;以学习有用的文本表示的方法。自监督学习在自然语言处理&#xff08;NLP&#xff09;领域中取得了显著的成果&#xff0c;如BERT、…

Live555源码阅读笔记:哈希表的实现(C++)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

算法日记day 20(中序后序遍历序列构造二叉树|最大、合并、搜索二叉树)

一、中序后序序列构造二叉树 题目&#xff1a; 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,…

使用SpringEvent解决WebUploader大文件上传解耦问题

目录 前言 一、SpringEvent涉及的相关组件 1、 事件&#xff08;Event&#xff09; 2、事件监听器 3、事件发布器 二、WebUploader大文件处理的相关事件分析 1、事件发布的时机 2、事件发布的代码 三、事件监听器及实际的业务处理 1、文件上传处理枚举 2、文件上传监…

pthread多线程

pthread库是linux系统的多线程库。上次写完longjmp和多线程的例子。就想用系统的真线程库改写一下读写线程的例子来和大家分享。真线程库应该比自己写的功能更完善&#xff0c;代码也更容易写吧&#xff01;… … 说到这里。我不知道接下来说什么了… …。也许是自己对多线程库…

ConstraintLayout实现原理分析

ConstraintLayout 是 Android 支持库中提供的一个非常强大的布局管理器&#xff0c;它允许开发者创建复杂的界面布局&#xff0c;并提供了比传统布局更多的灵活性。在 ConstraintLayout 中&#xff0c;视图之间可以通过约束来定义其位置关系&#xff0c;从而使得布局更加动态和…

Python+selenium web自动化测试知识点合集2

选择元素 对于百度搜索页面&#xff0c;如果我们想自动化输入“selenium”&#xff0c;怎么做呢&#xff1f; 这就是在网页中&#xff0c;操控界面元素。 web界面自动化&#xff0c;要操控元素&#xff0c;首先需要 选择 界面元素 &#xff0c;或者说 定位 界面元素 就是 先…

OD C卷 - 电脑病毒感染

电脑病毒感染 &#xff08;200&#xff09; 一个局域网内有n台电脑&#xff0c;编号为 1 -> n&#xff0c;电脑之间病毒感染时间用 t 表示&#xff1b;现在网络内已有一台电脑被病毒感染&#xff0c;求其感染所有其他电脑最少的时间&#xff0c;若最后有电脑不会被感染&…

URL重写

目录 步骤1 规则语法 Nginx URL重写规则语法 Apache URL重写规则语法 步骤2 规则配置 Apache URL重写规则配置 启用mod_rewrite模块 配置.htaccess文件 编写重写规则 测试重写规则 Nginx URL重写规则配置 配置server或location块 测试重写规则 步骤1 规则语法 Ngin…

如何使用Redis实现一个缓存策略

使用Redis实现一个缓存策略&#xff0c;主要涉及到数据的存储、读取、更新以及失效处理等方面。下面我将详细介绍如何使用Redis来设计和实现一个基本的缓存策略。 1. 确定缓存的数据结构和键命名规则 首先&#xff0c;你需要决定使用Redis中的哪种数据结构来存储缓存数据&…

解决在from pyhdf.SD import SD,SDC时No module named “hdfext“

文章内容仅用于自己知识学习和分享&#xff0c;如有侵权&#xff0c;还请联系并删除 &#xff1a;&#xff09; 1. 错误原因&#xff1a; 参考了多个博主的解决办法&#xff0c;结合自己的尝试&#xff0c;发现造成这个问题的主要原因是numpy版本太高 2. 解决方法 方法1&…

Day.31 | 1049.最后一块石头的重量II 494.目标和 474.一和零

1049.最后一块石头的重量II 要点&#xff1a;思路与分割等和子集很类似&#xff0c;把总数分成和最接近的两堆&#xff0c;然后用01背包的套路解答 class Solution { public:int lastStoneWeightII(vector<int>& stones) {int sum 0;for (int i : stones)sum i;i…

C++客户端Qt开发——界面优化(QSS)

1.QSS 如果通过QSS设置的样式和通过C代码设置的样式冲突&#xff0c;则QSS优先级更高 ①基本语法 选择器{属性名&#xff1a;属性值; } 例如&#xff1a; QPushButton {color: red; } 1>指定控件设置样式 #include "widget.h" #include "ui_widget.h&qu…

Unity Editor免登录启动 无需UnityHub

Unity Editor免登录启动项目无需UnityHub&#xff0c;命令行启动项目。需要开发Unity项目&#xff0c;就必须使用 Unity Hub来管理你的项目&#xff0c;还必须要申请一个免费许可&#xff0c;确实有点麻烦&#xff0c;官方已经提供了相关命令行&#xff0c;来直接使用Unity Edi…

qt--做一个拷贝文件器

一、项目要求 使用线程完善文件拷贝器的操作 主窗口不能假死主窗口进度条必须能动改写文件大小的单位&#xff08;自适应&#xff09; 1TB1024GB 1GB1024MB 1MB1024KB 1KB1024字节 二、所需技术 1.QFileDialog 文件对话框 QFileDialog也继承了QDialog类&#xff0c;直接使用静态…

Redis缓存数据库进阶——Redis与分布式锁(6)

分布式锁简介 1. 什么是分布式锁 分布式锁是一种在分布式系统环境下&#xff0c;通过多个节点对共享资源进行访问控制的一种同步机制。它的主要目的是防止多个节点同时操作同一份数据&#xff0c;从而避免数据的不一致性。 线程锁&#xff1a; 也被称为互斥锁&#xff08;Mu…

TypeScript学习篇-类型介绍使用、ts相关面试题

文章目录 基础知识基础类型: number, string, boolean, object, array, undefined, void(代表该函数没有返回值)enum(枚举): 定义一个可枚举的对象typeinterface联合类型: |交叉类型: &any 类型null 和 undefinednullundefined never类型 面试题及实战1. 你觉得使用ts的好处…