有向图_节点间路径路径--python数据结构

字典创建有向图,查找图节点之间的路径,最短路径,所有路径

 

"""
参考文档:
https://www.python.org/doc/essays/graphs/
"""

# 此有向图 有六个节点 (A-F) 和八个弧
"""
它可以由以下Python数据结构表示:
这是一个字典,其键是图形的节点。
对于每个键,相应的值是一个列表,其中包含由来自此节点的直接连接的节点;即两点直接连接
这很简单(更简单的是,节点可以用数字而不是名称来表示,但名称更方便,可以很容易地携带更多信息,例如城市名称)。
"""
from collections import deque

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

# 找到一个符合条件的路径
"""让我们编写一个简单的函数来确定两个节点之间的路径。
它采用图形以及开始和结束节点作为 参数。
它将返回包含路径的节点列表(包括开始节点和结束节点)。如果找不到路径,则返回 None。
同一节点在返回的路径上不会出现多次(即它不会包含循环)。
该算法使用了一种称为回溯的重要技术:它依次尝试每种可能性,直到找到解决方案。
"""


def find_path(graph, start, end, path=[]):
    path = path + [start]  # 路径,每一次递归调用时,把当前结点加入已经访问的集合中去
    print("path:%s" % path)
    if start == end:
        return path
    if start not in graph:  # 仅存在此节点 不作为弧头出现,仅作为弧尾[数据结构唐朔飞]
        return None  # 递归结束的条件
    print("graph[{}]:{}".format(start, graph[start]))
    for node in graph[start]:  # 依次访问start的邻接顶点node
        if node not in path:  # 同一节点在返回的路径上不会出现多次
            print("node:{}".format(node))
            newpath = find_path(graph, node, end, path)  # 递归调用时传入参数path
            # print("newpath:{}".format(newpath))
            # newpath=False
            if newpath:
                # print("if--newpath:{}".format(newpath))
                return newpath  # 找到一条路径便结束循环
    return None


"""
更改上函数以返回所有路径的列表(不带循环),而不是它找到的第一个路径
"""


# 找到所有的路径
def find_all_paths(graph, start, end, path=[]):
    path = path + [start]
    if start == end:
        return [path]
    if start not in graph:
        return []
    paths = []
    for node in graph[start]:
        if node not in path:
            newpaths = find_all_paths(graph, node, end, path)
            for newpath in newpaths:
                paths.append(newpath)  # 找到的路径加入路径列表
    return paths


# 最短路径
def find_shortest_path(graph, start, end, path=[]):
    path = path + [start]
    if start == end:
        return path
    if start not in graph:
        return None
    shortest = None
    for node in graph[start]:
        if node not in path:
            newpath = find_shortest_path(graph, node, end, path)
            if newpath:
                if shortest is None or len(newpath) < len(shortest):
                # if not shortest or len(newpath) < len(shortest):
                    shortest = newpath
    return shortest

"""
find_shortest_path可以使用BFS[广度优先搜索]在线性时间内完成。
此外,线性BFS更简单
"""

# path = find_path(graph, 'D', 'C')
# print(path)
# #---------------------------
# paths = find_all_paths(graph, 'A', 'C')
# print(paths)
# row = 1
# for path in paths:
#     print(row, end=":")
#     print(path)
#     row = row + 1
# #---------------------------
shortest = find_shortest_path(graph, 'A', 'D')
print(shortest)

  

posted @ 2022-02-17 18:12  def_Class  阅读(901)  评论(0编辑  收藏  举报