python實現圖的廣度優先搜素算法並打印最短路徑

from collections import deque


def create_graph():
    """採用鄰接表方式儲存圖"""
    graph = {}
    graph['A'] = ['B', 'C']
    graph['B'] = ['D']
    graph['C'] = ['E']
    graph['D'] = []
    graph['E'] = ['D']
    return graph


def search(graph, start, target):
    """
    廣度優先搜索,從stat起始到target是否有路徑,並打印最短路徑
    :param graph: 圖
    :param start: 起始點
    :param target: 目標點
    :return: 是否存在
    """
    print("start :" + start)

    # 創建一個隊列用於廣度優先搜索
    search_queue = deque()
    search_queue += graph[start]

    # 記錄已經被檢查的節點(防止閉環,死循環)
    searched = [start]

    # 如果隊列爲空,則該圖中沒有target
    while search_queue:
        # 先從隊列中取出一個節點
        point = search_queue.popleft()
        # 該節點如果沒被查找過,則進行檢查
        if point not in searched:
            # 如果該節點,爲target,則找到並打印最短路徑
            if point == target:
                print("search :" + point)
                searched.append(point)
                # 打印最短路徑
                path = get_path(searched, graph)
                print(" ".join(path))
                return True
            # 如果當前節點不是target,則把其鄰居入隊並把該節點加入被檢查列表中
            else:
                search_queue += graph[point]
                searched.append(point)
    print("not searched")
    return False


def get_path(searched_list, graph):
    """
    打印最短路徑(回溯法)
    思路:從target往上回溯,
    (1)判斷當前節點是否爲起始點,否則走(2),是則(4)
    (2)循環被檢查點列表並尋找第一個爲當前節點的父節點,
    (3)將父節點置爲當前節點並結束本次尋找,重新走(2)
    (4)逆序列表則爲最短路徑
    """
    print("searched: " + str(searched_list))
    target = searched_list[-1]
    path = [target]
    while target != searched_list[0]:
        for i in searched_list:
            if target in graph[i]:
                target = i
                path.append(i)
                break
    return path[::-1]


if __name__ == '__main__':
    graph = create_graph()
    search(graph, 'A', 'E')

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章