当前位置: 首页 > news >正文

【数据结构与算法】图的搜索——广度优先遍历、最小生成树

图的表示

  1. 邻接链表: 用字典实现.有向图的邻接链表的总长度等于图的边个数;无向图的邻接链表的总长度等于图的边个数的2倍.
  2. 邻接矩阵:用于最短路径算法.

Disjoint Set 数据结构

该数据结构维护一个不相交动态集的集合,每个集合有一个代表,不关心谁做代表。
支持三种操作:
MAKE_SET(x)
FIND_SET(x)
UNION(x,y)

应用

确定无向图的连通分量:

MAKE_CONNECTED_COMPONENTS(G):for each v in G.V:MAKE_SET(v)for each (u,v) in G.E:if FIND_SET(u) != FIND_SET(v):UNION_SET(u,v)

判断无向图中两个结点是否在同一个连通分量:

IS_SAME_COMPONENTS(u,v):return FIND_SET(u) == FIND_SET(v)

链表表示

  1. 一个链表对应一个子集,链表头包含head和tail属性,head指向第一个对象,tail指向最后一个对象。
  2. 合并操作的耗时分析
struct Obj;struct LinkedList{LinkedList(char n) {}Obj* head;Obj* tail;
};struct Obj{char n;Obj* next;LinkedList* ll;
};

有根树表示

每棵树的根包含集合的代表。
使用启发式策略实现合并操作
首先,增加rank属性,

MAKE_SET(x):x.p = xx.rank = 0
UNION(x,y):LINK(FIND_SET(x), FIND_SET(y))
LINK(u,v):
if u.rank > v.rank:v.p = u
else:u.p = vif u.rank == v.rank:v.rank += 1

带有路径压缩的FIND_SET

FIND_SET(x):
if x.p != x:x.p = FIND_SET(x.p)
return x.p

图的搜索算法

图搜索算法是一些图算法的开始步骤,或被优化成其他的图算法.

广度优先遍历

使用队列,先进后出遍历节点,使用节点内的一个变量记录其是否已被遍历,图采用邻接链表形式输入

Col = enum.Enum("Color", ("White", "Gray", "Black"))class Vertex:def __init__(self, u, col, pi):self._cnt += 1self.u = uself.col = colself.pi = piself.d = math.infdef __repr__():return "%s"%self.u
def BFS(G, s):#初始化初节点s外,其他节点均标记为为被访问,深度设为无穷大s.col = Grays.d = 0s.pi = NoneQ = []while Q:u = Q.pop(0)for i in G[u]:if i.col == Col.White:i.col = Col.Grayi.d = u.d + 1i.pi = uQ.append(i)u.col = Col.Black

BFS同时生成广度优先搜索树,对于每个从源结点s到可以到达的结点v,广度优先搜索树中从源结点s到结点v的简单路径即图中从s到v的最短路径.该算法可以用于有向图\无向图.
注意权重图暂时无法求其最短路径.

最短路径

  1. 打印最短路径
    使用广度优先搜索,记录每个节点的前驱
def PrintPath(G,s,e,path=[]):if e == s:path.append(e)print(e)returnif not e.pi:print("No path from",s,"to",e)else:PrintPath(G,s,e.pi,path)print(e)path.append(e)

深度优先搜索

发现时刻与完成时刻

强连通分量

其指内部两两结点可以相互到达的最大结点集合.

SCC(G):DFS(G)compute G.T按照结点的结束时刻降序遍历的DFS(G.T) 返回深度优先搜索森林中的树,即强连通分量

最小生成树

连接所有结点的最小权重的图边集合的子集
求MST的算法采用贪心策略,每一个时刻生长MST的一条边,贪心策略管理的边集合A遵循如下循环不变式:
每次循环前,A是某MST的子集.
安全边:这样的边,加入A后循环不变式仍成立的边.
切割:顶点集的一个划分
横跨切割:一条边的两个结点在两个集合中
轻量级边:满足某指定性质的权重最轻的边
尊重:边集合A中每条边未横跨一切割,称该切割尊重A
安全边定理:A是MST的一个子集,切割尊重A,某边是横跨该切割的轻量级边,则该边是A的安全边.

连通图G中权重最小的一条边(u, v)一定是G的某个最小生成树中的一条边。采用反证法实现,假设(u, v)不是任一个最小生成树中的一条边,设T是一个MST,其中有一个结点x连接u,设R=T-(x,u),则
w ( T ) = w ( R ) + w ( x , u ) > w ( R ) + w ( u , v ) w(T)=w(R)+w(x,u)>w(R)+w(u,v) w(T)=w(R)+w(x,u)>w(R)+w(u,v)
可见T的权重不是最小的生成树,与已知矛盾。

相关文章:

  • Java基础知识学习:深入理解Java中的类与对象,Java重要知识点概念性解释,结合实例讲解请看下一篇博文
  • Ansible file文件模块 设置文件的属性,比如创建文件、创建链接文件、删除文件
  • 《白话C++》第10章 STL和boost,Page88 std::shared_ptr常用功能02
  • 数据分析 — 动画图 pyecharts
  • 服务端和客户端以及前后端相关概念区分
  • GPT-3 训练自己的数据教程详解
  • Java学习心得感悟
  • 安全基础~通用漏洞6
  • springboot文件上传需要的配置
  • 【软考中级备考笔记】计算机体系结构
  • 四、详解Redis集群
  • 嵌入式学习记录20
  • LNMP搭建discuz论坛
  • 主客体标记技术在主机安全防护中的应用
  • JavaScript 继承的方式和优缺点
  • [LeetCode] Wiggle Sort
  • AHK 中 = 和 == 等比较运算符的用法
  • Angular 响应式表单 基础例子
  • CODING 缺陷管理功能正式开始公测
  • isset在php5.6-和php7.0+的一些差异
  • JAVA 学习IO流
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • 分布式熔断降级平台aegis
  • 规范化安全开发 KOA 手脚架
  • 前端工程化(Gulp、Webpack)-webpack
  • 巧用 TypeScript (一)
  • 使用Swoole加速Laravel(正式环境中)
  • 算法---两个栈实现一个队列
  • 微信开放平台全网发布【失败】的几点排查方法
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 正则学习笔记
  • scrapy中间件源码分析及常用中间件大全
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • (52)只出现一次的数字III
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (三)elasticsearch 源码之启动流程分析
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (转)Sql Server 保留几位小数的两种做法
  • (转)创业家杂志:UCWEB天使第一步
  • (转)用.Net的File控件上传文件的解决方案
  • .naturalWidth 和naturalHeight属性,
  • .net 无限分类
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .NET中 MVC 工厂模式浅析
  • @Mapper作用
  • @selector(..)警告提示
  • @TableLogic注解说明,以及对增删改查的影响
  • [ 隧道技术 ] 反弹shell的集中常见方式(四)python反弹shell
  • [04]Web前端进阶—JS伪数组
  • [Android学习笔记]ScrollView的使用
  • [Bzoj4722]由乃(线段树好题)(倍增处理模数小快速幂)