【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,一经查实,立即删除!

相关文章

我如何预测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 …

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

深度学习数据自动编码器意见 (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;直接下一步下一步安装即可&…

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

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

图深度学习-第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;反正我就是这么认为的…

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

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

项目经济规模的估算方法_估算英国退欧的经济影响

项目经济规模的估算方法On June 23 2016, the United Kingdom narrowly voted in a country-wide referendum to leave the European Union (EU). Economists at the time warned of economic losses; the Bank of England produced estimates that that GDP could be as much …

奇迹网站可视化排行榜]_外观可视化奇迹

奇迹网站可视化排行榜]When reading a visualization is what we see really what we get?阅读可视化内容时&#xff0c;我们真正看到的是什么&#xff1f; This post summarizes and accompanies our paper “Surfacing Visualization Mirages” that was presented at CHI …

机器学习 量子_量子机器学习:神经网络学习

机器学习 量子My last articles tackled Bayes nets on quantum computers (read it here!), and k-means clustering, our first steps into the weird and wonderful world of quantum machine learning.我的最后一篇文章讨论了量子计算机上的贝叶斯网络( 在这里阅读&#xf…

BZOJ 1176: [Balkan2007]Mokia

一道CDQ分治的模板题&#xff0c;然而我De了一上午Bug...... 按时间分成左右两半&#xff0c;按x坐标排序然后把y坐标丢到树状数组里&#xff0c;扫一遍遇到左边的就add,遇到右边的query 几个弱智出了bug的点&#xff0c; 一是先分了左右两半再排序&#xff0c;保证的是这次的左…

深入理解InnoDB(1)—行的存储结构

1.InnoDB页的简介 页&#xff08;Page&#xff09;是 Innodb 存储引擎用于管理数据的最小磁盘单位。常见的页类型有数据页、Undo 页、系统页、事务数据页等 2.InnoDB行的存储格式 我们插入MySQL的记录在InnoDB中可能以4中行格式存储&#xff0c;分别是Compact、Redundant、D…

boltzmann_推荐系统系列第7部分:用于协同过滤的Boltzmann机器的3个变体

boltzmannRecSys系列 (RecSys Series) Update: This article is part of a series where I explore recommendation systems in academia and industry. Check out the full series: Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, and Part 7.更新&#xff1a; 本文是我探索…

深入理解InnoDB(2)—页的存储结构

1. 记录头信息 上一篇博客说到每行记录都会有记录头信息&#xff0c;用来记录每一行的一些属性 Compact行记录的记录头信息为例 1.1 delete_mask 这个属性标记着当前记录是否被删除&#xff0c;占用1个二进制位&#xff0c;值为0的时候代表记录并没有被删除&#xff0c;为1的…

爬虫神经网络_股市筛选和分析:在投资中使用网络爬虫,神经网络和回归分析...

爬虫神经网络与AI交易 (Trading with AI) Stock markets tend to react very quickly to a variety of factors such as news, earnings reports, etc. While it may be prudent to develop trading strategies based on fundamental data, the rapid changes in the stock mar…

深入理解InnoDB(3)—索引的存储结构

1. 索引的各种存储结构及其优缺点 1.1 二叉树 优点&#xff1a; 二叉树是一种比顺序结构更加高效地查找目标元素的结构&#xff0c;它可以从第一个父节点开始跟目标元素值比较&#xff0c;如果相等则返回当前节点&#xff0c;如果目标元素值小于当前节点&#xff0c;则移动到左…

深入理解InnoDB(4)—索引使用

1. 索引的代价 在了解索引的代价之前&#xff0c;需要再次回顾一下索引的数据结构B树 如上图&#xff0c;是一颗b树&#xff0c;关于b树的定义可以参见B树&#xff0c;这里只说一些重点&#xff0c;浅蓝色的块我们称之为一个磁盘块&#xff0c;可以看到每个磁盘块包含几个数据…

双城记s001_双城记! (使用数据讲故事)

双城记s001Keywords: Data science, Machine learning, Python, Web scraping, Foursquare关键字&#xff1a;数据科学&#xff0c;机器学习&#xff0c;Python&#xff0c;Web抓取&#xff0c;Foursquare https://br.pinterest.com/pin/92816442292506979/https://br.pintere…

web前端面试总结

2019独角兽企业重金招聘Python工程师标准>>> 摘要&#xff1a;前端的东西特别多&#xff0c;面试的时候我们如何从容应对&#xff0c;作为一个老兵&#xff0c;我在这里分享几点我的经验。 一、javascript 基础(es5) 1、原型&#xff1a;这里可以谈很多&#xff0c;…

tableau破解方法_使用Tableau浏览Netflix内容的简单方法

tableau破解方法Are you struggling to perform EDA with R and Python?? Here is an easy way to do exploratory data analysis using Tableau.您是否正在努力使用R和Python执行EDA&#xff1f; 这是使用Tableau进行探索性数据分析的简单方法。 Lets Dive in to know the …