DFS

https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Graphs/Implementation%20of%20Depth%20First%20Search.ipynb

https://leetcode.com/problems/binary-tree-paths/#/solutions

Nodes and References Implementation of a Tree

class BinaryTree(object):
def __init__(self,rootObj):
self.key = rootObj
self.leftChild = None
self.rightChild = None def insertLeft(self,newNode):
if self.leftChild == None:
self.leftChild = BinaryTree(newNode)
else:
t = BinaryTree(newNode)
t.leftChild = self.leftChild
self.leftChild = t def insertRight(self,newNode):
if self.rightChild == None:
self.rightChild = BinaryTree(newNode)
else:
t = BinaryTree(newNode)
t.rightChild = self.rightChild
self.rightChild = t def getRightChild(self):
return self.rightChild def getLeftChild(self):
return self.leftChild def setRootVal(self,obj):
self.key = obj def getRootVal(self):
return self.key

Implementation of Depth-First Search

This algorithm we will be discussing is Depth-First search which as the name hints at, explores possible vertices (from a supplied root) down each branch before backtracking. This property allows the algorithm to be implemented succinctly in both iterative and recursive forms. Below is a listing of the actions performed upon each visit to a node.

  • Mark the current vertex as being visited.
  • Explore each adjacent vertex that is not included in the visited set.

We will assume a simplified version of a graph in the following form:

graph = {'A': set(['B', 'C']),
'B': set(['A', 'D', 'E']),
'C': set(['A', 'F']),
'D': set(['B']),
'E': set(['B', 'F']),
'F': set(['C', 'E'])}

Connected Component

The implementation below uses the stack data-structure to build-up and return a set of vertices that are accessible within the subjects connected component. Using Python’s overloading of the subtraction operator to remove items from a set, we are able to add only the unvisited adjacent vertices.

def dfs(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
for nxt in graph[start] - visited:
dfs(graph, nxt, visited)
return visited dfs(graph, 'A')
{'A', 'B', 'C', 'D', 'E', 'F'}

 

The second implementation provides the same functionality as the first, however, this time we are using the more succinct recursive form. Due to a common Python gotcha with default parameter values being created only once, we are required to create a new visited set on each user invocation. Another Python language detail is that function variables are passed by reference, resulting in the visited mutable set not having to reassigned upon each recursive call.

def dfs(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
for nxt in graph[start] - visited:
dfs(graph, nxt, visited)
return visited dfs(graph, 'A')
{'A', 'B', 'C', 'D', 'E', 'F'}   

Paths

We are able to tweak both of the previous implementations to return all possible paths between a start and goal vertex. The implementation below uses the stack data-structure again to iteratively solve the problem, yielding each possible path when we locate the goal. Using a generator allows the user to only compute the desired amount of alternative paths.

def dfs_paths(graph, start, goal):
stack = [(start, [start])]
while stack:
(vertex, path) = stack.pop()
for nxt in graph[vertex] - set(path):
if nxt == goal:
yield path + [nxt]
else:
stack.append((nxt, path + [nxt])) list(dfs_paths(graph, 'A', 'F'))
[['A', 'B', 'E', 'F'], ['A', 'C', 'F']]

Implementation of Breadth First Search

An alternative algorithm called Breath-First search provides us with the ability to return the same results as DFS but with the added guarantee to return the shortest-path first. This algorithm is a little more tricky to implement in a recursive manner instead using the queue data-structure, as such I will only being documenting the iterative approach. The actions performed per each explored vertex are the same as the depth-first implementation, however, replacing the stack with a queue will instead explore the breadth of a vertex depth before moving on. This behavior guarantees that the first path located is one of the shortest-paths present, based on number of edges being the cost factor.

We'll assume our Graph is in the form:

graph = {'A': set(['B', 'C']),
'B': set(['A', 'D', 'E']),
'C': set(['A', 'F']),
'D': set(['B']),
'E': set(['B', 'F']),
'F': set(['C', 'E'])}

Connected Component

Similar to the iterative DFS implementation the only alteration required is to remove the next item from the beginning of the list structure instead of the stacks last.

def bfs(graph, start):
visited, queue = set(), [start]
while queue:
vertex = queue.pop(0)
if vertex not in visited:
visited.add(vertex)
queue.extend(graph[vertex] - visited)
return visited bfs(graph, 'A')
{'A', 'B', 'C', 'D', 'E', 'F'}
 

Paths

This implementation can again be altered slightly to instead return all possible paths between two vertices, the first of which being one of the shortest such path.

def bfs_paths(graph, start, goal):
queue = [(start, [start])]
while queue:
(vertex, path) = queue.pop(0)
for next in graph[vertex] - set(path):
if next == goal:
yield path + [next]
else:
queue.append((next, path + [next])) list(bfs_paths(graph, 'A', 'F'))
[['A', 'C', 'F'], ['A', 'B', 'E', 'F']]
 

Knowing that the shortest path will be returned first from the BFS path generator method we can create a useful method which simply returns the shortest path found or ‘None’ if no path exists. As we are using a generator this in theory should provide similar performance results as just breaking out and returning the first matching path in the BFS implementation.

def shortest_path(graph, start, goal):
try:
return next(bfs_paths(graph, start, goal))
except StopIteration:
return None shortest_path(graph, 'A', 'F')
['A', 'C', 'F']
												

DFS and BFS的更多相关文章

  1. Clone Graph leetcode java(DFS and BFS 基础)

    题目: Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. ...

  2. 数据结构(12) -- 图的邻接矩阵的DFS和BFS

    //////////////////////////////////////////////////////// //图的邻接矩阵的DFS和BFS ////////////////////////// ...

  3. 数据结构(11) -- 邻接表存储图的DFS和BFS

    /////////////////////////////////////////////////////////////// //图的邻接表表示法以及DFS和BFS //////////////// ...

  4. 在DFS和BFS中一般情况可以不用vis[][]数组标记

    开始学dfs 与bfs 时一直喜欢用vis[][]来标记有没有访问过, 现在我觉得没有必要用vis[][]标记了 看代码 用'#'表示墙,'.'表示道路 if(所有情况都满足){ map[i][j]= ...

  5. 图论中DFS与BFS的区别、用法、详解…

    DFS与BFS的区别.用法.详解? 写在最前的三点: 1.所谓图的遍历就是按照某种次序访问图的每一顶点一次仅且一次. 2.实现bfs和dfs都需要解决的一个问题就是如何存储图.一般有两种方法:邻接矩阵 ...

  6. 图论中DFS与BFS的区别、用法、详解?

    DFS与BFS的区别.用法.详解? 写在最前的三点: 1.所谓图的遍历就是按照某种次序访问图的每一顶点一次仅且一次. 2.实现bfs和dfs都需要解决的一个问题就是如何存储图.一般有两种方法:邻接矩阵 ...

  7. 数据结构基础(21) --DFS与BFS

    DFS 从图中某个顶点V0 出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到(使用堆栈). //使用邻接矩阵存储的无向图的深度 ...

  8. dfs和bfs的区别

    详见转载博客:https://www.cnblogs.com/wzl19981116/p/9397203.html 1.dfs(深度优先搜索)是两个搜索中先理解并使用的,其实就是暴力把所有的路径都搜索 ...

  9. 邻接矩阵实现图的存储,DFS,BFS遍历

    图的遍历一般由两者方式:深度优先搜索(DFS),广度优先搜索(BFS),深度优先就是先访问完最深层次的数据元素,而BFS其实就是层次遍历,每一层每一层的遍历. 1.深度优先搜索(DFS) 我一贯习惯有 ...

  10. 判断图连通的三种方法——dfs,bfs,并查集

    Description 如果无向图G每对顶点v和w都有从v到w的路径,那么称无向图G是连通的.现在给定一张无向图,判断它是否是连通的. Input 第一行有2个整数n和m(0 < n,m < ...

随机推荐

  1. C++ 编译报错discards qualifiers [-fpermissive]

    声明了一个类 class Card { public: Card(const string&); int m_value; char m_suit; private: const static ...

  2. MySQL Online DDL的改进与应用

        本文简析Online DDL的实现原理与使用过程注意事项.       任何DDL操作,执行者都需要预先测试或者清晰了解这个操作会给数据库带来的影响是否是在业务期间数据库的可承受范围内,尤其是 ...

  3. IEnumerable<T>和IQueryable<T>

    建议29.区别LINQ查询中的IEnumerable<T>和IQueryable<T> LINQ查询方法一共提供了两类扩展方法,在System.Linq命名空间下,有两个静态类 ...

  4. 探索 vuex 2.0 以及使用 vuejs 2.0 + vuex 2.0 构建记事本应用

    前言 首先说明这并不是一个教程贴,而记事本应用是网上早有的案例,对于学习 vuex 非常有帮助.我的目的是探索 vuex 2.0 ,然后使用 vue 2.0 + vuex 2.0 重写这个应用,其中最 ...

  5. 如何有效快速提高Java服务端开发人员的技术水平?

    我相信很多工作了3-5年的开发人员都会经常问自己几个问题: 1.为什么总是感觉技术没有质的提高? 2.如何能够有效和快速的提高自身的技术水平? 3.如何进入到一个牛逼的大公司,认识牛逼的人? 这篇文章 ...

  6. ActiveMQ学习心得:连接池的简单实现和模板模式的应用

    一.安装activemq 下载地址:https://archive.apache.org/dist/activemq/5.13.0/apache-activemq-5.13.0-bin.zip 下载完 ...

  7. 如何给远程主机开启mysql远程登录权限

    # 如何给远程主机开启mysql远程登录权限 > 在千锋学习PHP的有些学员会在阿里或者腾讯云去购买自己的云服务器.在初级阶段的项目上线时会遇到一个问题,就是无法使用远程连接工具操作自己线上的m ...

  8. bzoj2884 albus就是要第一个出场

    Description 已知一个长度为n的正整数序列A(下标从1开始), 令 S = { x | 1 <= x <= n }, S 的幂集2^S定义为S 所有子集构成的集合.定义映射 f ...

  9. DirectFB 之 动画播放初步

    在基于linux的嵌入式仿真平台开发中,终端的美观和可定制是一个重要的问题.单调的"白纸黑字"型表现方式可谓大煞风景.改造linux控制台使之美观可定制地展示开机信息和logo成为 ...

  10. 整合最优雅SSM框架:SpringMVC + Spring + MyBatis

    我们看招聘信息的时候,经常会看到这一点,需要具备SSH框架的技能:而且在大部分教学课堂中,也会把SSH作为最核心的教学内容. 但是,我们在实际应用中发现,SpringMVC可以完全替代Struts,配 ...