图的遍历:BFS和DFS


title: ‘图的遍历:BFS和DFS’
date: 2019-09-03 19:24:07
tags: python,数据结构
categories: 计算机理论

图的遍历

BFS(广度优先搜索)

算法原理及步骤

按照广度优先原则遍历图,利用了队列,有点像树的层次遍历。广度优先遍历的结果不唯一。整个遍历过程大概是这样的:给定一个起始顶点,将该起始顶点入队

  1. 顶点出队,如果当前顶点未被标记访问,则访问该顶点,然后标记为已访问,如果当前顶点已访问则直接丢弃该顶点
  2. 当前访问顶点的邻接顶点入队
  3. 当队列不为空的时候,循环1,2步

算法流程

Created with Raphaël 2.2.0 初始化队列,初始顶点入队 出队 是否访问过该顶点? 跳过该顶点的访问 是否队空 结束BFS 访问 yes no yes no

算法实现

    # 广度优先遍历
    def bfs(self, start):
        if not self._invalid(start):
            raise GraphError("不存在" + start + "这样的顶点")
        queue = [start]  # 队列实现BFS
        seen = set(start)  # 记录访问过的顶点
        parent = {start: None}  # Node代表根节点,数组形式保存树
        result = []
        while queue.__len__() > 0:  # 队非空时
            vertex = queue.pop(0)  # 队首顶点出队
            nodes = self._graph[vertex]  # 获得其邻接顶点
            for node in nodes:
                if node not in seen:
                    queue.append(node)  # 其邻接顶点如果没有被访问,则入队,并且保留父顶点
                    seen.add(node)
                    parent[node] = vertex
            result.append(vertex)
        return result, parent

测试

例如遍历下图

20190825160305

具体的存储结构为:

    data = {
        "A": {"B": 5, "C": 1},
        "B": {"A": 5, "C": 2, "D": 1},
        "C": {"A": 1, "B": 2, "D": 4, "E": 8},
        "D": {"B": 1, "C": 4, "E": 3, "F": 6},
        "E": {"C": 8, "D": 3},
        "F": {"D": 6},
    }
    def test_bfs(self):
        print("bfs测试:")
        bfs, bfsparent = TestGraph.g.bfs("A")
        print("BFS:" + graph.GraphAL.printPath(bfs))
        print("BFS生成路径:" + bfsparent.__str__())
        print("BFS生成路径打印:" + graph.GraphAL.printTreePath(bfsparent).__str__())
        pass

20190829183358

DFS(深度优先搜索)

算法原理及步骤

DFS和BFS很像,不过DFS是深度优先的原则,具体实现是栈。

DFS遍历的结果不唯一。整个遍历过程大概是这样的:给定一个起始顶点,将该起始顶点入栈

  1. 顶点出栈,如果当前顶点未被标记访问,则访问该顶点,然后标记为已访问,如果当前顶点已访问则直接丢弃该顶点
  2. 当前访问顶点的邻接顶点入栈
  3. 当栈不为空的时候,循环1,2步
Created with Raphaël 2.2.0 初始化栈,初始顶点进栈 出栈 是否访问过该顶点? 跳过该顶点的访问 是否栈空 结束DFS 访问 yes no yes no

算法实现

    # 深度优先遍历
    def dfs(self, start):
        if not self._invalid(start):
            raise GraphError("不存在" + start + "这样的顶点")
        stack = [start]  # 栈实现DFS
        seen = set(start)  # 记录访问过的顶点
        parent = {start: None}  # Node代表根节点,数组形式保存树
        result = []
        while stack.__len__() > 0:  # 栈非空时
            vertex = stack.pop()  # 顶点出栈
            nodes = self._graph[vertex]  # 获取出栈顶点的邻接顶点
            for node in nodes:
                if node not in seen:
                    stack.append(node)
                    seen.add(node)
                    parent[node] = vertex
            result.append(vertex)
        return result, parent

测试

例如遍历下图

20190825160305

存储结构
    data = {
    
    
        "A": {
    
    "B": 5, "C": 1},
        "B": {
    
    "A": 5, "C": 2, "D": 1},
        "C": {
    
    "A": 1, "B": 2, "D": 4, "E": 8},
        "D": {
    
    "B": 1, "C": 4, "E": 3, "F": 6},
        "E": {
    
    "C": 8, "D": 3},
        "F": {
    
    "D": 6},
    }
测试结果
图的结构为:
('A', {'B': 5, 'C': 1})
('B', {'A': 5, 'C': 2, 'D': 1})
('C', {'A': 1, 'B': 2, 'D': 4, 'E': 8})
('D', {'B': 1, 'C': 4, 'E': 3, 'F': 6})
('E', {'C': 8, 'D': 3})
('F', {'D': 6})

dfs测试:
DFS:A->C->E->D->F->B
DFS生成路径:{'A': None, 'B': 'A', 'C': 'A', 'D': 'C', 'E': 'C', 'F': 'D'}
DFS生成路径打印:
A->B
A->C
A->C->D
A->C->E
A->C->D->F

猜你喜欢

转载自blog.csdn.net/weixin_41154636/article/details/100526910