宽度优先遍历BFS & 深度优先遍历DFS(python代码实现)

目录

宽度优先遍历

深度优先遍历

python代码

 扩展

加权图


宽度优先遍历

        先遍历与当前结点相邻的结点,再遍历深一层的结点,层层递进,直到找到和合适的结果。

 

ABCDEFGHIJK和ABCDEF

特点:求解问题时,大部分情况下,不需要遍历完整张图。

实现方法:队列。

应用:求无权图的最短路径。

遍历步骤:

1. 定义一个操作队列Que,一个记录已经扫描过节点的数组Arr和一个遍历结果数组res。

2. 给定起始节点start,执行起始节点入队和加入数组Arr。

3. 执行扫描(只要队列不为空):

        出队操作,并把出队节点v更新为新的起始节点start。        

        扫描起始节点start相邻(连接)的节点,通过Arr数组判断是否已被扫描过:

                若扫描过,则继续。

                若没有,则入队和加入数组Arr。

        当前出队的节点v加入结果数组res。

深度优先遍历

        一条路走到黑,走不通了再回到上一个岔路口,直到走完整张图。

ABDHIEJCFGK和ABDFEC

特点:求解问题时,需要遍历整张图。

实现方法:栈。

应用:求有多少个解,求有多少条路径,求最大路径等类似的问题。

遍历步骤:

1. 定义一个操作栈stack,一个记录已经扫描过节点的数组Arr和一个遍历结果数组res。

2. 给定起始节点start,执行起始节点入栈和加入数组Arr。

3. 执行扫描(只要栈不为空):

        出栈操作,并把出栈节点v更新为新的起始节点start。        

        扫描起始节点start相邻(连接)的节点,通过Arr数组判断是否已被扫描过:

                若扫描过,则继续。

                若没有,则入栈和加入数组Arr。

        当前出栈的节点v加入结果数组res。

注:BFS和DFS在遍历搜索时路径可能不唯一

如DFS:

 

python代码

宽度优先遍历

#  构造图
graph = {"A": ['B', 'C'],
         "B": ['A', 'C', 'D'],
         "C": ['A', 'B', 'D', 'E'],
         "D": ['B', 'C', 'E', 'F'],
         "E": ['C', 'D'],
         "F": ['D']}

# graph图结构,start_v起始结点
def BFS(graph, start_v):
    queue = []  # 队列
    check = set()  # 已经访问过
    queue.append(start_v)  # 放入起始结点
    check.add(start_v)  # 放入起始结点

    # 遍历访问图
    while len(queue) > 0:
        vertex = queue.pop(0)
        nodes = graph[vertex]
        # 从当前结点相连接的结点中寻找
        for v in nodes:
            # 判断是否已经访问过,没有则访问
            if v not in check:
                queue.append(v)
                check.add(v)
        print(vertex)  # 依次访问的节点


if __name__=="__main__":
    # 宽度优先遍历
    BFS(graph, 'A')

深度优先遍历

#  构造图
graph = {"A": ['B', 'C'],
         "B": ['A', 'C', 'D'],
         "C": ['A', 'B', 'D', 'E'],
         "D": ['B', 'C', 'E', 'F'],
         "E": ['C', 'D'],
         "F": ['D']}


# graph图结构,start_v起始结点
def DFS(graph, start_v):
    stack = []  # 栈
    check = set()  # 已经访问过
    stack.append(start_v)  # 放入起始结点
    check.add(start_v)  # 放入起始结点

    # 遍历访问图
    while len(stack) > 0:
        vertex = stack.pop()
        nodes = graph[vertex]
        # 从当前结点相连接的结点中寻找
        for v in nodes:
            # 判断是否已经访问过,没有则访问
            if v not in check:
                stack.append(v)
                check.add(v)
        print(vertex)  # 依次访问的节点

if __name__=="__main__":

    # 深度优先遍历
    DFS(graph, 'A')

 扩展

保存父结点

求最短距离(当前结点到起始结点)

graph = {"A": ['B', 'C'],
         "B": ['A', 'C', 'D'],
         "C": ['A', 'B', 'D', 'E'],
         "D": ['B', 'C', 'E', 'F'],
         "E": ['C', 'D'],
         "F": ['D']}

# 记录父节点,求最短路径(距离)
def BFSsuper(graph, start_v):
    queue = []  # 队列
    check = set()  # 已经访问过
    parent = {start_v: None}  # 记录父节点
    queue.append(start_v)  # 放入起始结点
    check.add(start_v)  # 放入起始结点

    # 遍历访问图
    while len(queue) > 0:
        vertex = queue.pop(0)
        nodes = graph[vertex]
        # 从当前结点相连接的结点中寻找
        for v in nodes:
            # 判断是否已经访问过,没有则访问
            if v not in check:
                queue.append(v)
                check.add(v)
                parent[v] = vertex
        #print(vertex)  # 依次访问的节点
    # 返回父结点
    return parent

if __name__=="__main__":
    # 扩展(记录父节点)
    start_v = 'A'
    parent = BFSsuper(graph, start_v)
    print('-----')
    print("结点", "父结点")
    for key in parent:
        print(key, parent[key])
    print('-----')

    # 求最短路径(距离),从一个节点到遍历的初始节点的路径,通过父节点查找,直到触顶结束
    node_start = 'E'
    print("结点{}到起始结点{}的最短路径为:" .format(node_start, start_v))
    while node_start != None:
        print(node_start, end=", ")
        node_start = parent[node_start]

加权图

dijkstra算法

import math
import heapq

weightedGrah = {"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 init_distance(graph, stat_v):
    distance = {stat_v: 0}  # 起始点距离标为0
    # 其它点距离标为正无穷
    for vertex in graph:
        if vertex != stat_v:
            distance[vertex] = math.inf
    return distance

# 加权图,dijkstra算法,求最短路径(距离)
def dijkstra(graph, start_v):
    # 创建优先队列
    pqueue = []
    heapq.heappush(pqueue, (0, start_v))
    check = set()  # 已经访问过
    parent = {start_v: None}  # 记录父节点
    distance = init_distance(graph, start_v)  # 统计当前结点到起始结点的距离

    while len(pqueue) > 0:
        pair = heapq.heappop(pqueue)
        dist = pair[0]
        vertex = pair[1]
        check.add(vertex)

        nodes = graph[vertex].keys()
        for v in nodes:
            if v not in check:
                # 确保最短距离
                if dist+graph[vertex][v] < distance[v]:
                    heapq.heappush(pqueue, (dist+graph[vertex][v], v))
                    parent[v] = vertex
                    distance[v] = dist+graph[vertex][v]
    return parent, distance

if __name__=="__main__":
    # 加权图
    parent, distance = dijkstra(weightedGrah, 'A')
    #print(parent)
    print(distance)

猜你喜欢

转载自blog.csdn.net/qq_41750911/article/details/124950559