1. 深度优先搜索

1.1 标记法探索迷宫

探索迷宫而不迷路的一种古老办法叫做Tremaux搜索(标记法),要探索迷宫中的所有通道,我们需要:

  1. 选择一条没有标记过的通道,在你走过的路上铺一条绳子;
  2. 标记所有你第一次路过的路口和通道;
  3. 当来到一个标记过的路口时(用绳子)回退到上个路口;
  4. 当回退到的路口已没有可走的通道时继续回退。

绳子可以保证你总能找到一条出路,标记则能保证你不会两次经过同一条通道或者同一个路口。

1.2 深度优先搜索算法

和Tremaux搜索类似,深度优先搜索,只需用一个递归方法来遍历所有顶点。在访问其中一个顶点时:

  1. 将它标记为已访问;
  2. 递归地访问它的所有没有被标记过的邻居顶点。

2. 广度优先搜索

问题是这样:给定一幅图和一个起点s,回答“从s到给定目的顶点v是否存在一条路径?如果有,找出其中最短的那条(所含边数最少)。”

2.1 广度优先搜索算法

广度优先搜索是这样的:要找到从s到v的最短路径,从s开始,在所有由一条边就可以到达的顶点中寻找v,如果找不到我们就继续在与s距离两条边的所有顶点中查找v,如此一直进行。

在程序视线中,我们一般使用一个队列来保存所有已经被标记过但其邻接表还未被检查过的顶点。

  1. 先将起点加入队列,然后重复以下步骤直到队列为空:
  2. 取队列中的下一个顶点v并标记它;
  3. 将与v相邻的所有未被标记过的顶点加入队列。

2.2 广度优先搜索和迷宫最短路径

广度优先搜索正是为了寻找迷宫的最短路径才出现的,因为:

  1. 队列总是包含零个或多个到起点的距离为k的顶点,之后是零个或多个到起点的距离为k+1的顶点,其中k为整数,起始值为0
  2. 这意味着顶点是按照它们和s的距离的顺序加入或者离开队列的
  3. 从顶点v加入队列到它离开队列之前,不可能找出到v的更短的路径
  4. 而在v离开队列之后发现的所有能够到达v的路径都不可能短于v在树中的路径长度

3. 最小生成树

图的生成树是它的一棵含有其所有顶点的无环连通子图。
一幅加权图的最小生成树(MST)是它的一棵权值(树中所有边的权值之和)最小的生成树。

最小生成树算法在设计各种类型的网络中都起到了重要的作用。

3.1 树的性质

  1. 用一条边连接树中的任意两个顶点都会产生一个新的环;
  2. 从树中删去一条边将会得到两棵独立的树。

3.2 切分定理

在一幅加权图中,给定任意的切分,它的横切边中的权重最小者必然属于图的最小生成树。

令e为权重最小的横切边,T为图的最小生成树。我们采用反证法:

  1. 假设T不包含e。
    1.1 那么如果将e加入T,得到的图必然含有一条经过e的环
    1.2 且这个环至少含有另一条横切边——设为f, f的权重必然大于e。
    1.3 那么我们删掉f而保留e就可以得到一棵权重更小的生成树。
  2. 这和我们的假设T矛盾

3.3 最小生成树的贪心算法

切分定理是解决最小生成树问题的所有算法的基础。

使用切分定理找到最小生成树的一条边,不断重复直到找到最小生成树的所有边。

  1. 首先从起点a开始,把a加入U集合
  2. 然后,寻找从与a有关联的边中,权重最小的那条边并且该边的终点b在顶点集合:(V-U)中,我们也把b加入到集合U中,并且输出边(a,b)的信息,这样我们的集合U就有:{a,b},
  3. 然后,我们寻找与a关联和b关联的边中,权重最小的那条边并且该边的终点在集合:(V-U)中,我们把c加入到集合U中,并且输出对应的那条边的信息,这样我们的集合U就有:{a,b,c}这三个元素了
  4. 依次类推,直到所有顶点都加入到了集合U。

如何才能(有效地)找到最小权重的横切边呢?Prim算法使用一条优先队列MinPQ<Edge>来根据权重比较所有边。

每当我们向树中添加了一条边之后,也向树中添加了一个顶点。要维护一个包含所有横切边的集合,就要将连接这个顶点和其他所有不在树中的顶点的边加入优先队列。

class Solution:def minCostConnectPoints(self, points: List[List[int]]) -> int:from queue import PriorityQueuecal = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])  # 计算曼哈顿距离的函数pq = PriorityQueue() visit = set(range(len(points)))  # 待访问的节点集res = 0pq.put((0, 0))  # (distance, point_id)while visit:  # 当没有访问完所有节点 dis, now = pq.get()  # 获取优先队列中最小的项 => (到扩展集中某最近点的距离,某最近点的序号)if now not in visit:  # 已访问过的直接跳过continuevisit.remove(now)  # 移除出待访问的节点集res += disfor i in visit:  # 构建扩展集,就是把当前点对所有未访问点的距离都求一遍# 以距离为cost丢进优先队列排序pq.put((cal(points[now], points[i]), i))return res

4. 最短路径

定义:在一幅加权有向图中,从顶点s到顶点t的最短路径是所有从s到t的路径中的权重最小者。

4.1 松弛技术

松弛这个术语来自于用一根橡皮筋沿着连接两个顶点的路径紧紧展开的比喻:放松一条边就类似于将橡皮筋转移到一条更短的路径上,从而缓解了橡皮筋的压力。

边的松弛:放松边v→w意味着检查从s到w的最短路径是否是先从s到v,然后再由v到w。

顶点的松弛:谨慎选择顶点,使得每次顶点松弛操作都能得出到达某个顶点的更短的路径,最后逐渐找出到达每个顶点的最短路径。

4.2 最优性条件

判断路径是否为最短路径的全局条件与在放松一条边时所检测的局部条件是等价的。

  1. 令G为一幅加权有向图,顶点s是G中的起点
  2. distTo[]是一个由顶点索引的数组,对于从s可达的所有顶点v,distTo[v]的值是从s到v的某条路径的长度,对于从s不可达的所有顶点v,该值为无穷大。
  3. 当且仅当对于从v到w的任意一条边e,这些值都满足distTo[w]<=distTo[v]+e.weight()时,它们是最短路径的长度。

必要性证明:
假设distTo[w]是从s到w的最短路径。如果对于某条从v到w的边e有distTo[w]>distTo[v]+e.weight(),那么从s到w(经过v)且经过e的路径的长度必然小于distTo[w],矛盾。因此最优性条件是必要的。

4.3 通用算法

将distTo[s]初始化为0,其他distTo[]元素初始化为无穷大,继续如下操作:

  1. 放松G中的任意边,直到不存在有效边为止。

对于任意从s可达的顶点w,在进行这些操作之后,distTo[w]的值即为从s到w的最短路径的长度。

4.4 Dijkstra算法实现最短路径树

通用算法并没有指定边的放松顺序。

Dijkstra算法主要特点是从起始点开始,每次都会为最短路径树添加一条顶点,这点距离始点距离最近且未被访问过,直到扩展到终点为止。

要实现Dijkstra算法,需要一条优先队列,以保存需要被放松的顶点并确认下一个被放松的顶点。

public void dijkstra(int s, int t) { // 从顶点s到顶点t的最短路径int[] predecessor = new int[this.v]; // 用来还原最短路径Vertex[] vertexes = new Vertex[this.v];for (int i = 0; i < this.v; ++i) {vertexes[i] = new Vertex(i, Integer.MAX_VALUE);}PriorityQueue queue = new PriorityQueue(this.v);// 小顶堆boolean[] inqueue = new boolean[this.v]; // 标记是否进入过队列vertexes[s].dist = 0;queue.add(vertexes[s]);inqueue[s] = true;while (!queue.isEmpty()) {Vertex minVertex= queue.poll(); // 取堆顶元素并删除if (minVertex.id == t) break; // 最短路径产生了for (int i = 0; i < adj[minVertex.id].size(); ++i) {Edge e = adj[minVertex.id].get(i); // 取出一条minVetex相连的边Vertex nextVertex = vertexes[e.tid]; // minVertex-->nextVertexif (minVertex.dist + e.w < nextVertex.dist) { // 更新next的distnextVertex.dist = minVertex.dist + e.w;predecessor[nextVertex.id] = minVertex.id;if (inqueue[nextVertex.id] == true) {queue.update(nextVertex); // 更新队列中的dist值} else {queue.add(nextVertex);inqueue[nextVertex.id] = true;}}}}// 输出最短路径System.out.print(s);print(s, t, predecessor);
}private void print(int s, int t, int[] predecessor) {if (s == t) return;print(s, predecessor[t], predecessor);System.out.print("->" + t);
}

图算法--深度优先/广度优先/最小生成树/最短路径相关推荐

  1. Algorithm:C++语言实现之图论算法相关(图搜索广度优先BFS、深度优先DFS,最短路径SPF、带负权的最短路径Bellman-ford、拓扑排序)

    Algorithm:C++语言实现之图论算法相关(图搜索广度优先BFS.深度优先DFS,最短路径SPF.带负权的最短路径Bellman-ford.拓扑排序) 目录 一.图的搜索 1.BFS (Brea ...

  2. 【算法】【殊途同归】搜索算法之(深度优先 || 广度优先) (约束条件 || 限界函数)

    对于所谓的分支限界法和回溯法,我们完全可以更加灵活,请看表格. 深度优先 广度优先 约束条件 限界函数 算法 策略 √ √ 回溯法 局部判定 √ √ √ 分支限界法 局部判定 √ √ √ 加限界的回溯 ...

  3. python广度优先算法最短路径_最短路径问题的Dijkstra算法 -python

    最短路径问题的Dijkstra算法 是由荷兰计算机科学家艾兹赫尔·戴克斯特拉提出.迪科斯彻算法使用了广度优先搜索解决非负权有向图的单源最短路径问题,算法最终得到一个最短路径树>    .该算法常 ...

  4. 数据结构—图(Part Ⅱ)—最小生成树 最短路径

    目录 最小生成树 普里姆(Prim)算法 算法实现 运行结果 程序分析 克鲁斯卡尔(Kruskal)算法 算法实现 运行结果 程序分析 最短路径 广度优先搜索(BFS)算法 算法实现 运行结果 程序分 ...

  5. 深度优先 广度优先

    如图所示,爬去网站的url时,深度优先按照这个顺序爬取  利用递归实现树的广度优先遍历 A B D      E I      C F G H(递归实现) def depth-tree(tree-co ...

  6. 程序员的算法课(18)-常用的图算法:广度优先(BFS)

    一.广度优先搜索介绍 广度优先搜索算法(Breadth First Search),又称为"宽度优先搜索"或"横向优先搜索",简称BFS. 它的思想是:从图中某 ...

  7. 二叉树遍历(深度优先+广度优先)

    文章目录 1.深度优先遍历 1.1 先序遍历 1.2 中序遍历 1.3 后序遍历 2. 广度优先遍历 3.验证结果 参考文献 二叉树的遍历分为两类,一类是深度优先遍历,一类是广度优先遍历. 1.深度优 ...

  8. 《算法笔记》10.5小节——图算法专题->最小生成树

    10.5.1 最小生成树及其性质 最小生成树是无向图中的一棵树,涵盖图G的所有顶点,并且边之和最小 最小生成树的三个性质: 1.是树,边数=顶点数-1 2.对于给定的图,最小生成树可以不唯一,但是边权 ...

  9. 人工智能笔记 2.1人工智能导论- 1.什么是AI,深度优先,广度优先,最优路径

    人工智能是什么 人工智能是关于算法通过表示得以呈现的约束条件而表示支持针对思维,感知和行动的有机体模型 (algorithms enabled by constriants exposed by re ...

最新文章

  1. 在普通PC上安装XENSERVER 6.2
  2. vue 多页面iframe不刷新_Vue中iframe保持活动状态(不刷新)
  3. 电脑端京东的我的订单html+css页面_什么是前端和后端开发?写给即将迈入前端开发领域的朋友...
  4. 不是说一个源程序中只能有一个public类?怎么内部类可以用public?
  5. SLAM:VSLAM简介之详细攻略
  6. 最短路径(弗洛伊德算法)
  7. 【EOJ Monthly 2019.02 - B】解题(思维,抽屉原理,暴力,模运算,优化,tricks)
  8. 对扩展openflow协议的一点思考
  9. 二阶系统响应指标图_二阶系统单位阶跃响应.ppt
  10. matlab kdj,kdj指标详什么时候买入,kdj指标详解四大绝技
  11. 串行口终端乱码的解决.
  12. 2022年茶艺师(中级)考试题模拟考试题库模拟考试平台操作
  13. Twitter首席科学家离职 高层动荡仍持续
  14. 逍遥模拟器使用指南(四、逍遥安卓模拟器电脑版xposed框架教程)
  15. 计算机的纸牌游戏打不开啥原因,win10系统游戏纸牌打不开解决方法 - Win10专业版官网...
  16. 方舟建立服务器显示cmd,家庭电脑建方舟服务器
  17. DirectShow2
  18. Endpoint的中文意思
  19. 业务流程(学习笔记)
  20. 边下边看 七款P2P下载软件全能大比拼

热门文章

  1. Spring学习之旅(二):Bean的高级装配之解决装配歧义性
  2. 02数据库表的相关操作
  3. 6-4cifar10数据介绍读取处理(下)
  4. 智能手环功能模块设计_可能是目前最好用的智能手环,国产芯加持,颜值与实力并存...
  5. 机器学习和深度学习_算法测评 | 机器学习VS深度学习
  6. 奶块显示正常登录服务器但进不去,奶块服务器流畅怎么进不进去quest; | 手游网游页游攻略大全...
  7. CentOS 7 上安装 MySQL5.7
  8. 解决django3.x manage命令makemigrations无法创建数据表
  9. linux nohup后台执行管道操作
  10. pandas 按照固定的列顺序排序,并补足缺失列