【Python算法】遍历(Traversal)、深度优先(DFS)、广度优先(BFS)

图结构:

  非常强大的结构化思维(或数学)模型。如果您能用图的处理方式来规范化某个问题,即使这个问题本身看上去并不像个图问题,也能使您离解决问题更进一步。

  在众多图算法中,我们常会用到一种非常实用的思维模型--遍历(traversal):对图中所有节点的探索及访问操作。

 

图的一些相关概念:

  简单图(Simple graph):无环并且无平行边的图.

  路(path):内部点互不相同的链。

  如果无向图G中每一对不同的顶点x和y都有一条路,(即W(G)=1,连通分支数)则称G是连通图,反之称为非连通图。

  两端点相同的路(即闭路)称为圈(cycle)。

  树(tree)是无圈连通无向图。树中度数为1的结点称为树的叶结点。树中度数大于1的结点称为树的分支节点或内部结点。

  不相交的若干树称为森林(forest),即森林的每个连通分支是树。

  定理1:T是树<=>T中无环,且任何不同两顶点间有且仅有一条路。

  定理2:T是树<=>T连通且|e|=n-1,|e|为T的边数,n为T的顶点数。

  由根到某一顶点v的有向路的长度,称为顶点v的层数(level)。根树的高度就是顶点层数的最大值。

 

深度优先搜索:

  求连通简单图G的一棵生成树的许多方法中,深度优先搜索(depth first search)是一个十分重要的算法。

基本思想:

  任意选择图G的一个顶点V0作为根,通过相继地添加边来形成在顶点V0开始的路,其中每条新边都与路上的最后一个顶点以及不在路上的一个顶点相关联。

  继续尽可能多地添加边到这条路。若这条路经过图G的所有顶点,则这条路即为G的一棵生成树;

  若这条路没有经过G的所有顶点,不妨设形成这条路的顶点顺序V0,V1,......,Vn。则返回到路里的次最后顶点V(n-1).

    若有可能,则形成在顶点v(n-1)开始的经过的还没有放过的顶点的路;

    否则,返回到路里的顶点v(n-2)。

  然后再试。重复这个过程,在所访问过的最后一个顶点开始,在路上次返回的顶点,只要有可能就形成新的路,直到不能添加更多的边为止。

  深度优先搜索也称为回溯(back tracking)

栗子:

  用深度优先搜索来找出图3-9所示图G的生成树,任意地从顶点d开始,生成步骤显示在图3-10。

  

 

广度优先搜索:

  可用广度优先搜索(breadth first search)来产生连通简单图的生成树。

基本思想:

  从图的顶点中任意第选择一个根,然后添加与这个顶点相关联的所有边,在这个阶段添加的新顶点成为生成树里1层上的顶点,任意地排序它们。

  下一步,按照顺序访问1层上的每一个顶点,只要不产生回路,就添加与这个顶点相关联的每个边。这样就产生了树里2的上的顶点。遵循同样的原则继续下去,经有限步骤就产生了生成树。

栗子:

  用广度优先搜索找出图3-9所示图G的生成树,选择顶点f作为根:

  

 

两种著名的基本遍历策略:

  深度优先搜索(depth-first search)

  广度优先搜索(breadth-first search)

 

找出图的连通分量:

  如果一个图中的任何一个节点都有一条路径可以到达其他各个节点,那么它就是连通的。

  连通分量:目标图中最大(且独立)的连通子图。

  从图中的某个部分开始,逐步扩大其连通子图的确认范围,直至它再也无法向外连通为止。

def walk(G,s,S=set()):P,Q=dict(),set()P[s]=None                    # s节点没有前任节点Q.add(s)                     # 从s开始搜索while Q:u=Q.pop()for v in G[u].difference(P,S):   # 得到新节点Q.add(v)P[v]=u               # 记录前任节点return Pdef components(G):comp = []seen = set()for u in range(9):if u in seen: continueC = walk(G, u)seen.update(C)comp.append(C)return compif __name__ == "__main__":a, b, c, d, e, f, g, h, i= range(9)N = [{b, c, d},   # a{a, d},      # b{a,d},       # c{a,c,d},     # d{g,f},       # e{e,g},       # f{e,f},       # g{i},         # h{h}          # i
    ]comp = components(N)print(comp)

 

深度优先搜索:

  

  递归版的深度优先搜索 :

def rec_dfs(G,s,S=None):if S is None:S = set()S.add(s)for u in G[s]:if u in S:coontinuerec_dfs(G,u,S)

  迭代版的深度优先搜索 :

def iter_dfs(G,s):S,Q=set(),[]Q.append(s)while Q:u = Q.pop()if u in S:continueS.add(u)Q.extend(G[u])yield uif __name__ == "__main__":a, b, c, d, e, f, g, h, i = range(9)G = [{b, c, d, e, f},  # a{c, e},           # b{d},              # c{e},              # d{f},              # e{c, g, h},        # f{f, h},           # g{f, g}            # h
         ]print(list(iter_dfs(G,a)))       # [0, 5, 7, 6, 2, 3, 4, 1]

  通用性的图遍历函数

def traverse(G,s,qtype=set()):  S,Q=set(),qtype()  Q.add(s)  while Q:  u=Q.pop()  if u in S:continue  S.add(u)  for v in G[u]:  Q.add(v)  yield u  class stack(list):  add=list.append  g=list(traverse(G,0,stack))  

 

基于深度优先搜索的拓扑排序

  

def dfs_topsort(G):S,res=set(),[]
def recurse(u):if u in S: returnS.add(u)for v in G[u]:recurse(v)res.append(u)
for u in G:recurse(u)res.reverse()
return resif __name__=="__main__":a, b, c, d, e, f, g, h, i = range(9)G = {'a': set('bf'),'b': set('cdf'),'c': set('d'),'d': set('ef'),'e': set('f'),'f': set('')}res = dfs_topsort(G)

 

迭代深度的深度优先搜索

def iddfs(G,s):  yielded=set()  def recurse(G,s,d,S=None):  if s not in yielded:  yield s  yielded.add(s)  if d==0:return  if S is None:S=set()  S.add(s)  for u in G[s]:  if u in S:continue  for v in recurse(G,u,d-1,S):  yield v  n=len(G)  for d in range(n):  if len(yielded)==n:break  for u in recurse(G,s,d):  yield u  if __name__=="__main__":  a, b, c, d, e, f, g, h, i= range(9)  N = [  {b, c, d},  # a  {a, d},     # b  {a,d},      # c  {a,b,c},    # d  {g,f},      # e  {e,g},      # f  {e,f},      # g  {i},        # h  {h}         # i  
    ]  G = [{b,c,d,e,f},#a    {c,e},      # b    {d},        # c    {e},        # d    {f},        # e    {c,g,h},    # f    {f,h},      # g    {f,g}       # h    
   ]  p=list(iddfs(G,0))         # [0, 1, 2, 3, 4, 5, 6, 7]  m=list(iddfs(N,0))         # [0, 1, 2, 3]  

 

广度优先搜索

import collections  
def bfs(G,s):  P,Q={s:None},collections.deque([s])  while Q:  u=Q.popleft()  for v in G[u]:  if v in P:continue  P[v]=u  Q.append(v)  return P  

 

强连通分量

  如果有向图的任何一对结点间是相互可达的,则称这个有向图是强连通的

def tr(G):  GT={}  for u in G:GT[u]=set()  for u in G:  for v in G[u]:  GT[v].add(u)  return GT  
def scc(G):  GT=tr(G)  sccs,seen=[],set()  for u in dfs_topsort(G):  if u in seen:continue  C=walk(GT,u,seen)  seen.update(C)  sccs.append(C)  return sccs  def dfs_topsort(G):  S,res=set(),[]  def recurse(u):  if u in S:return  S.add(u)  for v in G[u]:  recurse(v)  res.append(u)  for u in G:  recurse(u)  res.reverse()  return res  def walk(G,s,S=set()):  P,Q=dict(),set()  P[s]=None  Q.add(s)  while Q:  u=Q.pop()  print("u: ",u)  print("S:",S)  for v in G[u].difference(P,S):  Q.add(v)  P[v]=u  return P  if __name__=="__main__":  a, b, c, d, e, f, g, h, i= range(9)  G={    'a':set('bc'),    'b':set('edi'),    'c':set('d'),    'd':set('ah'),    'e':set('f'),    'f':set('g'),  'g':set('eh'),  'h':set('i'),  'i':set('h')  }  sccs=scc(G)  # [{'a': None, 'd': 'a', 'c': 'd', 'b': 'd'}, {'e': None, 'g': 'e', 'f': 'g'}, {'h': None, 'i': 'h'}]  

 

转载于:https://www.cnblogs.com/5poi/p/7466760.html

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

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

相关文章

r语言编程基础_这项免费的统计编程课程仅需2个小时即可学习R编程语言基础知识

r语言编程基础Learn the R programming language in this course from Barton Poulson of datalab.cc. This is a hands-on overview of the statistical programming language R, one of the most important tools in data science.从datalab.cc的 Barton Poulson学习本课程中…

leetcode 81. 搜索旋转排序数组 II(二分查找)

已知存在一个按非降序排列的整数数组 nums &#xff0c;数组中的值不必互不相同。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转 &#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nu…

使用ViewContainerRef探索Angular DOM操作技术

每当我阅读中遇到&#xff0c;关于Angular中使用DOM的内容时&#xff0c;总会看到一个或几个这样的类&#xff1a;ElementRef&#xff0c;TemplateRef&#xff0c;ViewContainerRef等等。 不幸的是&#xff0c;虽然其中的一些被Angular文档或相关文章所讲述&#xff0c;但是我还…

numpy1

1、NumPy包含的内容 1、ndarrray&#xff0c;高效的多维数组&#xff0c;提供了基于数组的便捷算术操作以及灵活的广播功能&#xff1b; 2、对所有数组对象进行快速的矩阵计算&#xff0c;而无需编写循环&#xff1b; 3、提供对硬盘中的数据的读写工具&#xff0c;并对内存映射…

我如何预测10场英超联赛的确切结果

Is there a way to predict the outcome of any soccer game with 100% accuracy? The honest and simplest answer is…. no. Regardless of what your fantasy football friends say, there is absolutely no way to be 100% certain, but there is a proven, mathematical …

多迪技术总监揭秘:PHP为什么是世界上最好的语言?

PHP这么一个脚本语言&#xff0c;虽然他是web开发中&#xff0c;使用者最多的语言&#xff0c;最快最简单的语言&#xff0c;生态环境和社区积累最深厚的语言&#xff0c;作为最好的编程语言&#xff0c;多迪技术总监为你介绍&#xff1a;PHP为什么是世界上最好的语言&#xff…

aws数据库同步区别_了解如何通过使用AWS AppSync构建具有实时数据同步的应用程序

aws数据库同步区别AWS AppSync automatically updates the data in web and mobile applications in real time, and updates data for offline users as soon as they reconnect. AWS AppSync会自动实时更新Web和移动应用程序中的数据&#xff0c;并在离线用户重新连接后立即为…

leetcode 153. 寻找旋转排序数组中的最小值(二分查找)

已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,2] 若旋转 4 次&#xff0…

test1

test1 转载于:https://www.cnblogs.com/Forever77/p/11434403.html

打印风车旋转效果

1 while True: 2 for i in["/","-","\\","|"]: 3 print "%s\r" %i, 转载于:https://www.cnblogs.com/feifei-cyj/p/7469333.html

深度学习数据自动编码器_如何学习数据科学编码

深度学习数据自动编码器意见 (Opinion) When I first wanted to learn programming, I coded along to a 4 hour long YouTube tutorial.刚开始学习编程时&#xff0c;我编写了长达4个小时的YouTube教程。 “Great,” I thought after finishing the course. “I know how to …

Angular 5.0 学习2:Angular 5.0 开发环境的搭建和新建第一个ng5项目

1.安装Node.js 在开始工作之前&#xff0c;我们必须设置好开发环境。如果你的机器上还没有Node.js和npm&#xff0c;请先安装它们。去Node.js的官网&#xff0c;https://nodejs.org/en/&#xff0c;点击下载按钮&#xff0c;下载最新版本&#xff0c;直接下一步下一步安装即可&…

leetcode 154. 寻找旋转排序数组中的最小值 II(二分查找)

已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,4,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,4] 若旋转 7 次&#xff0…

robot:根据条件主动判定用例失败或者通过

场景&#xff1a; 当用例中的断言部分需要满足特定条件时才会执行&#xff0c;如果不满足条件时&#xff0c;可以主动判定该用例为passed状态&#xff0c;忽略下面的断言语句。 如上图场景&#xff0c;当每月1号时&#xff0c;表中才会生成上月数据&#xff0c;生成后数据不会再…

golang go语言_在7小时内学习快速简单的Go编程语言(Golang)

golang go语言The Go programming language (also called Golang) was developed by Google to improve programming productivity. It has seen explosive growth in usage in recent years. In this free course from Micheal Van Sickle, you will learn how to use Go step…

使用MUI框架,模拟手机端的下拉刷新,上拉加载操作。

套用mui官方文档的一句话&#xff1a;“开发者只需关心业务逻辑&#xff0c;实现加载更多数据即可”。真的是不错的框架。 想更多的了解这个框架&#xff1a;http://dev.dcloud.net.cn/mui/ 那么如何实现下拉刷新&#xff0c;上拉加载的功能呢&#xff1f; 首先需要一个容器&am…

图深度学习-第1部分

有关深层学习的FAU讲义 (FAU LECTURE NOTES ON DEEP LEARNING) These are the lecture notes for FAU’s YouTube Lecture “Deep Learning”. This is a full transcript of the lecture video & matching slides. We hope, you enjoy this as much as the videos. Of cou…

Git上传项目到github

2019独角兽企业重金招聘Python工程师标准>>> Git入门 个人理解git就是一个上传工具&#xff0c;同时兼具和svn一样的版本控制功能&#xff08;此解释纯属本人个人观点&#xff09; Github是什么 github就是一个分布式版本管理系统&#xff08;反正我就是这么认为的…

ionic4 打包ios_学习Ionic 4并开始创建iOS / Android应用

ionic4 打包iosLearn how to use Ionic 4 in this full course for beginners from Awais Mirza. Ionic Framework is the free, open source mobile UI toolkit for developing high-quality cross-platform apps for native iOS, Android, and the web—all from a single Ja…

robot:当用例失败时执行关键字(发送短信)

使用场景&#xff1a; 当用例失败时需要通知对应人员&#xff0c;则需要在Teardown中&#xff0c;使用关键字Run Keyword If Test Failed Send Message关键字为自定义关键字&#xff0c;${content}为短信内容&#xff0c;${msg_receiver}为短信接收者列表。 当然执行成功时需要…