手把手:四色猜想、七桥问题…程序员眼里的图论,了解下?

地图渲染——四色定理的实现(AO+C++) 上个星期实现了唯一值渲染后,一直打算实现四色渲染的效果。关于四色定理我也是最近才听说,感觉真的挺奇妙的,所以也吸引我去实现它。     正好在网上找到了一篇有关四色渲染的学习资料,大致思路和算法也参考了这篇文章。     首先,四色定理就是无论多么错杂的地图,只须要用四种色彩就能将它区分隔来,这四种颜色可以使相邻的面颜色都不相同。这是1852年英国人弗朗西斯提出来的。直到1976年,美国数学家 阅读详情

大数据文摘作品

编译:张礼俊、王一丁、xixi、修竹、Apricock、惊蛰、Chloe、龙牧雪


长文预警!本文作者Vardan Grigoryan是一名后端程序员,但他认为图论(应用数学的一个分支)的思维应该成为程序员必备。


本文从七桥问题引入,将会讲到图论在Airbnb房屋查询、推特推送更新时间、Netflix和亚马逊影片/商品个性化推荐、Uber寻找最短路线中的应用,附有大量手把手代码和手绘插图,值得收藏。


图论的傻瓜式教程


图论是计算机科学中最重要、最有趣,同时也是最容易被误解的领域之一。理解并使用图论有助于我们成为更好的程序员。图论思维应该成为我们的思维方式之一。


先看一下枯燥的定义……图是一组节点V和边E的集合,包括有序对G =(V,E)……��


在试图研究理论并实现一些算法的同时,我发现自己经常因为这些理论和算法太过艰深而被卡住……


事实上,理解某些东西的最好方法就是应用它。我们将展示图论的各种应用,及其详细的解释。


对于经验丰富的程序员来说,下面的描述可能看起来过于详细,但相信我,作为一个过来人,详细的解释总是优于简洁的定义的。


所以,如果你一直在寻找一个“图论的傻瓜式教程”,你看这篇文章就够了。



免责声明

免责声明1:我不是计算机科学/算法/数据结构(特别是图论方面)的专家。 我没有参与本文谈及的公司的任何项目。本文问题的解决办法并非完美,也有改进的空间。 如果你发现任何问题或不合理的地方,欢迎你发表评论。 如果你在上述某家公司工作或参与相应的软件项目,请提供实际解决方案。请大家耐心阅读,这是一篇很长的文章。


免责声明2:这篇文章在信息表述的风格上与其它文章有所不同,看起来可能图片也与其所在部分的主题不是十分契合,不过耐心的话,相信最终会发现自己对图片有完整的理解。


免责声明3:本文主要是将初级程序员作为受众而编写的。在考虑目标受众的同时,但更专业的人员也将通过阅读本文有所发现。


哥尼斯堡的七桥问题


让我们从经常在图论书中看到的“图论的起源”开始——哥尼斯堡七桥问题。


故事发生在东普鲁士的首都哥尼斯堡(今俄罗斯加里宁格勒),普莱格尔河(Pregolya)横贯其中。十八世纪在这条河上建有七座桥,将河中间的两个岛和河岸联结起来。


现在这个地区变成这样啦


问题是如何才能不重复,不遗漏地一次走完七座桥,最后回到出发点。他们当时没有互联网,所以就得找些问题来思考消磨时间。以下是18世纪哥尼斯堡七座桥梁的示意图。



你可以尝试一下,用每座桥只通过一次的方式来走遍整个城市。“每座桥”意味着不应该有没有通过的桥。“只有一次”意味着不得多次通过每座桥。如果你对这个问题很熟悉,你会知道无论怎么努力尝试这都是不可能的;再努力最终你还是会放弃。


Leonhard Euler(莱昂哈德·欧拉)


有时,暂时放弃是合理的。欧拉就是这样应对这个问题的。虽然放弃了正面解决问题,但是他选择了去证明“每座桥恰好走过并只走过一遍是不可能的”。让我们假装“像欧拉一样思考”,先来看看“不可能”。



图中有四块区域——两个岛屿和两个河岸,还有七座桥梁。先来看看连接岛屿或河岸的桥梁数量中的模式(我们会使用“陆地”来泛指岛屿和河岸)。


每块区域连接桥梁的数量


只有奇数个的桥梁连接到每块陆地。这就麻烦了。


两座桥与陆地的例子


在上面的插图中很容易看到,如果你通过一座桥进入一片陆地,那你可以通过走第二座桥离开这片陆地。


每当出现第三座桥时,一旦穿过桥梁进入,那就没法走上每座桥且只走一次离开了。如果你试图将这种推理推广到一块陆地上,你可以证明,如果桥梁数量是偶数的话,总有办法离开这块陆地,但如果桥梁数量是奇数,就不能每桥走且只走一次的离开。试着记住这个结论。


如果添加一个新的桥梁呢?通过下面这张图,我们可以观察各个陆地所连接的桥的数量变化及其影响。


注意新出现的桥


现在我们有两个偶数和两个奇数。让我们画一条包括了新桥梁的路线。


Wow


桥梁的数量是偶数还是奇数至关重要。现在的问题是:我们知道了桥梁数量是否就能够断定问题可不可解?为了解决问题桥的数量必须是偶数吗?欧拉找到了一种方法证明这个问题。而且,更有趣的是,具有奇数个桥梁连接的陆地数量也很重要。


欧拉开始将陆地和桥梁“转换”成我们所知道的图。以下是代表哥尼斯堡七桥的图的样子(请注意,我们“暂时”增加的桥并不在图中):




需要特别注意的一点是对问题的概括和抽象。无论何时你解决一个具体的问题,最重要的是归纳类似问题的解决方案。在这个例子中,欧拉的任务是归纳桥梁问题,以便能在未来推广到类似问题上,比如说世界上所有的桥梁问题。可视化还有助于以不同视角来看问题。下面的每张图都表示前面描述的桥梁问题:



所以说图形化可以很好地描绘问题,但我们需要的是如何使用图来解决哥尼斯堡问题。观察从圆圈中出来的线的数量。从专业角度而言,我们将称之为“节点”(V),以及连接它们的“边”(E)。V代表节点(vertex),E代表边(edge)。



下一个重要的概念就是所谓的节点自由度,即入射(连接)到节点的边的数量。在上面的例子中,与陆地连结的桥的数目可以视为图的节点自由度。



欧拉证明了,一次并仅有一次穿过每条边(桥)来遍历图(陆地)严格依赖于节点(陆地)自由度。由这些边组成的路径叫做欧拉路径。欧拉路径的长度是边的数量。


有限无向图G(V,E)的欧拉路径是一条使G的每条边出现并且只出现一次的路径。如果G有一条欧拉路径,那么就可以称之为欧拉图。


定理:一个有限无向连通图是一个欧拉图,当且仅当只有两个节点有奇数自由度或者所有节点都有偶数自由度。在后一种情况下,曲线图的每条欧拉路径都是一条闭环,前者则不是。



左图正好有两个节点具有奇数自由度,右图则是所有节点都是奇数自由度


首先,让我们澄清上述定义和定理中的新术语。


有限图是具有有限数量的边和节点的图。


图可以是有向图也可以是无向图,这是图的有趣特性之一。举个非常流行的关于有向图和无向图的例子,Facebook vs. Twitter。Facebook的友谊关系可以很容易地表示为无向图,因为如果Alice是Bob的朋友,那么Bob也必须是Alice的朋友。 没有方向,都是彼此的朋友。




还要注意标记为“Patrick”的节点,它有点特别,因为没有任何连接的边。但“Patrick”点仍然是图的一部分,但在这种情况下,我们会说这个图是不连通的,它是非连通图(与“John”,“Ashot”和“Beth”相同,因为它们与图的其他部分分开)。在连通图中没有不可达的节点,每对节点之间必须有一条路径。


与Facebook的例子相对,如果Alice在Twitter上关注Bob,那不需要Bob回粉Alice。所以一个“关注”关系必须有一个方向来指示是谁关注谁,图表示中就是哪个节点(用户)有一个有向边(关注)到另一个节点。



现在,知道什么是有限连通无向图后,让我们回到欧拉图:



为什么我们首先讨论了哥尼斯堡桥问题和欧拉图呢?通过思考实际问题和上述解决方案,我们触及了图理论的基本概念(节点,边,有向,无向),避免了只有枯燥的理论。然而我们还未完全解决欧拉图和上述问题。我们现在应该转向图的计算机表示,因为这对我们程序员来说是最重要的。通过在计算机程序中表示图,我们能设计一个标记图路径的算法,从而确定它是否是欧拉路径。


图表示法:介绍


这是一项非常乏味的任务,要有耐心。记得数组和链表之间的竞争吗?如果你需要对元素进行快速访问,请使用数组;如果你需要对元素进行快速插入/删除等修改,请使用列表。


我不相信你会在“如何表示列表”的问题上有困惑。但是就图的表示而言,实际上却有很多麻烦,因为首先需要你决定的是用什么来表示一个图。相信我,你不会喜欢这个过程的。邻接表,邻接矩阵,还是边表?抛个硬币来决定?


决定了用什么表示图了吗?我们将从一棵树开始。你应该至少看过一次二叉树(以下不是二叉搜索树)。



仅仅因为它由顶点和边组成,它就是一个图。你也许还记得最常见的一棵二叉树(至少在教科书中)的样子。


对于已经熟悉“树”的人来说,这段文字可能看起来太过细致了,但我还是要详细解释以确保我们的理解一致(请注意,我们仍在使用伪代码)。


BinTreeNode<Apple>* root = new BinTreeNode<Apple>("Green");

root->left = new BinTreeNode<Apple>("Yellow");
root->right = new BinTreeNode<Apple>("Yellow 2");

BinTreeNode<Apple>* yellow_2 = root->right;

yellow_2->left = new BinTreeNode<Apple>("Almost red");
yellow_2->right = new BinTreeNode<Apple>("Red");


如果你不熟悉树,请仔细阅读上面的伪代码,然后按照此插图中的步骤操作:


颜色只是为了有好的视觉表现


虽然二叉树是一个简单的节点“集合”,每个节点都有左右子节点,但二叉搜索树却由于应用了一个允许快速键查找的简单规则显得更加有用。


二叉搜索树(BST)对各节点排序。你可以自由地使用任何你想要的规则来实现你的二叉树(尽管可能根据规则改变它的名字,例如最小堆或最大堆),BST一般满足二分搜索属性(这也是二叉搜索树名字的来源),即“每个节点的值必须大于其左侧子树中的任何值,并且小于其右侧子树中的任何值”。


关于“大于”的阐述有个非常有趣的评论。这对于BST的性质也至关重要。当将“大于”更改为“大于或等于”,插入新节点后,BST可以保留重复的值,否则只将保留一个具有相同值的节点。你可以在网上找到关于二叉搜索树非常好的文章,我们不会提供二叉搜索树的完整实现,但为了保持一致性,我们还是会举例说明一个简单的二叉搜索树。



Airbnb房屋查询实例:二叉搜索树


树是一种非常实用的数据结构,你可能在项目开始的时候没有打算应用树这种结构,但是不经意间就用到了。让我们来看一个构想的但非常有价值的例子,关于为什么要首先使用二叉搜索树。


二叉搜索树中这个名字中包括了“搜索”,所以基本上所有需要快速查找的东西都应该放进二叉搜索树中。应该不代表必须,在编程中最重要的事情就是要牢记用合适的工具解决问题。在许多案例中用复杂度为O(N)的简单链表查找比复杂度为O(logN)的二叉搜索树查找更好。


通常我们会使用一个库实现BST,最常用的是C++里面的std::set或是std::map,然而在这个教程中,我们完全可以重新造轮子,重写一个BST库(BST几乎可以通过任何通用的编程语言库实现,你可以找到你喜欢的语言的相应文档)。


下面是我们将要解决的问题:



Airbnb房屋搜索截图


如何用一些过滤器尽可能快地根据一些查询语句搜索住房是一个困难的问题;当我们考虑到Airbnb储存了上百万的房源信息后这个问题会变得更困难。


所以当用户搜索住房时,他们有机会接触到数据库中大概四百万个房源记录。当然,网站主页上只能显示有限个排名靠前的住房列表,并且用户几乎不会好奇地去浏览住房列表里百万量级的住房信息。我没有任何关于Airbnb的分析,但是我们可以用一个在编程中叫做“假设”的强大工具,所以我们假设一个用户最多浏览一千套房源。


这里最重要的因素是实时用户数量,因为这会导致数据结构、数据库选择的不同和项目结构的不同。可以很明显的看出,如果只有100个用户,我们一点不必担心,但如果一个国家的实时用户数量远超过百万量级的阙值,我们必须要十分明智地做每一个决定。


是的,“每一个”决定都需要明智的决策。这就是为什么公司在服务方面力求卓越而雇佣最好的员工。Google, Facebook, Airbnb, Netflix, Amazon, Twitter还有许多其他的公司,他们需要处理大量的数据,做出正确的选择以通过每秒数以百万的数据来服务数以百万的实时用户,这一切从招聘好的工程师开始。这就是为什么我们程序员在面试中要与数据结构、算法和解决问题的逻辑作斗争,因为他们所需要工程师需要具有以最快最有效的方式解决大规模问题的能力。


现在案例是,一个用户访问Airbnb主页并且希望找到最合适的房源。我们如何解决这个问题?(注意这是一个后端问题,所以我们不需关心前端或者网络阻塞或者多个http链接一个http或者Amazon EC2链接主集群等等)。


首先,我们已经熟悉了一种强大的编程工具(是假设而不是抽象),让我们从假设我们所处理的数据都能放在内存中。你也可以假设我们的内存已经足够大。多大的内存是足够的呢?这是另外一个好问题。储存真实的数据需要多大的内存,如果我们正在处理四百万单位个数据(假设),而且我们或许知道每个单位的大小,那么我们就可以轻易的算出需要的内存大小,例如,4M*一个单位的大小。让我们来考虑一个“home”对象和他的特征,


事实上,让我们考虑至少一个在解决问题时需要处理的特征(一个“home”就是一个单位)。我们把它表示为C++语言结构的伪代码,你可以很轻松的将它转换成MongoDB架构或者其它你想要的形式,我们只是讨论特征名字和类型(想象为节约空间所使用的二元位域或位集)。


// feel free to reorganize this struct to avoid redundant space
// usage because of aligning factor
// Remark 1: some of the properties could be expressed as enums,
// bitset is chosen for as multi-value enum holder.
// Remark 2: for most of the count values the maximum is 16
// Remark 3: price value considered as integer,
// int considered as 4 byte.
// Remark 4: neighborhoods property omitted
// Remark 5: to avoid spatial queries, we're
// using only country code and city name, at this point won't consider
// the actual coordinates (latitude and longitude)
struct AirbnbHome
{
 wstring name; // wide string
 uint price;
 uchar rating;
 uint rating_count;
 vector<string> photos; // list of photo URLs
 string host_id;
 uchar adults_number;
 uchar children_number; // max is 5
 uchar infants_number; // max is 5
 bitset<3> home_type;
 uchar beds_number;
 uchar bedrooms_number;
 uchar bathrooms_number;
 bitset<21> accessibilit

七桥问题大作业 哥尼斯堡七桥问题的总结研究,包含相关定理极其证明,另有现实应用 立即下载

相关推荐

四色问题 数据结构

英国人格思里于1852年提出四色问题(four colour problem,亦称四色猜想),即在为一平面或一球面的地图着色时,假定每一个国家在地图上是一个连通域,并且有相邻边界线的两个国家必须用不同的颜色,问是否只要四种颜色就可完成着色。现在给定一张地图,要求对这张地图上的国家用不超过四种的颜色进行染色。 要求建立地图的邻接矩阵存储结构,输入国家的个数和相邻情况,输出每个国家的颜色代码。

七阶段循环流程图.pptx

七阶段循环流程图.pptx,pptfans_12b22c8718f405f.pptx

C++碰撞检测库FCL安装(MinGW,CMake)

FCL碰撞检测库、libccd\Eigen库编译配置,全流程问题记录

weixin_45650767的博客 4674

从MIPS汇编到C语言:手把手教你用Mars模拟器理解指令集(附实战代码)

本文详细介绍了如何使用Mars模拟器从MIPS汇编过渡到C语言编程,通过实战代码解析ADD、LW、BEQ等指令集与C语言结构的对应关系。内容涵盖环境搭建、算术运算、内存访问、条件分支及函数调用等核心概念,帮助读者深入理解MIPS指令分类和计算机底层运行机制。

weixin_26821003的博客 357

一条龙开发指南:MCP AI Agent 理论+项目实战开发你的MCP Server

MCP(Model Connection Protocol)是Anthropic于2024年推出的AI模型连接协议,旨在为AI模型提供开放、通用的标准化接口,类似于“USB-C”接口,使AI模型能够无缝连接各种数据源和工具。MCP通过标准化协议解决了AI系统集成中的碎片化问题,提升了开发效率和系统可靠性。开发者可以通过简单的配置,快速接入不同的MCP Server,实现AI模型的多样化应用。MCP支持多种协议,如Stdio、SSE等,并通过JSON-RPC格式进行数据传输。文章还以腾讯云代码助手为例,展示了

杨不易呀 3045

Mac用户必看:Typora最新版永久激活+弹窗屏蔽保姆级教程(附崩溃解决方案)

本文为Mac用户提供了一份详尽的Typora最新版永久激活与弹窗屏蔽教程。通过修改关键JS文件,实现软件激活状态并彻底关闭成功提示弹窗。文章深入剖析了操作原理,并重点提供了解决由此引发的多文档崩溃问题的实用临时方案,同时客观讨论了该方法的局限性与潜在风险。

wine的专栏 2349

RAGFlow核心引擎DeepDoc之PDF解析大起底

本文深入解析RAGFlow中的deepdoc模块,重点介绍了pdf文档解析器的实现细节。deepdoc包含parser(文档解析器)和vision(视觉处理)两大核心功能,其中pdf解析是最复杂的部分。文章详细剖析了PdfParser类的设计架构,包含PlainParser(基础文本提取)、RAGFlowPdfParser(核心处理流水线)和VisionParser(视觉扩展)三个类,它们通过统一的__call__方法返回标准化结果。还具体讲解了初始化过程如何加载OCR引擎、布局识别模型、表格结构识别器等关

yxkong的专栏 2023

194、产线 Camera 校准与测试:终检测试项、规格线制定与量产数据监控

摘要: 文章通过"绿屏门"案例揭示了产线Camera校准测试中的关键问题,提出了系统性改进方案。在终检测试方面,建议增加多增益暗电流测试、混合光源色温测试和径向亮度梯度测试,覆盖用户真实场景。规格线制定强调用CPK替代固定百分比,区分硬软规格并建立动态调整机制。量产监控需关注参数趋势、边界模组分布,构建失效模式数据库。实践建议包括测试冗余设计、规格余量预留、自动化监控、供应商数据共享和人工抽检保留。文章指出Camera产线质量管控需形成"测试设计-规格优化-数据监控"闭环,以数据驱动决策避免客诉风险。

sundong_81的博客 192

【读代码】从claude skills到superpowers项目

最近claude skills成了大热门,今天一起看下GitHub 上的开源技能框架,他将“工作流”封装为“技能” (Skills)。本文尝试剖析该项目的技能粒度定义、多技能关联架构、应用逻辑等。与传统的 Function Calling 不同,Superpowers 中的 Skill 定义粒度并非“原子操作”,而是**“认知模式” (Cognitive Mode) 或“工作阶段”**。

kakaZhui的博客 1920

3. 动手运行第一个 SAP Fiori Elements 应用(ListReport 类型)

这个代理服务器能够自动监听我们 Fiori Elements 应用里向 ES5 Demo 系统发送的 OData 请求,拦截这个请求,并通过 Node.js 代码向 ES5 服务器转发,拿到响应数据后再交还给 Fiori Elements 应用。后者对自己发出的请求被代理这件事情一无所知。本文的任务是,大家按照我的介绍,在本地成功运行笔者准备的这个 Fiori Elements 应用。的错误消息, 说明大家安装的 Node.js 版本没有达到本地运行 Fiori Elements 的最低要求。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1671

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

上一篇: 业界 | 福布斯:2018年机器学习试点及实施数量将翻倍
下一篇: 用Python入门不明觉厉的马尔可夫链蒙特卡罗(附案例代码)
BigDataDigest
博客等级 码龄9年 448粉丝 500原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值