Dijkstra算法实现最快路径

       Dijkstra算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。

      下面,我用python来举例详细介绍这个算法

     问题如下:

                    如图所示(我们规定箭头上的数字为时间)现有如下路径图,我们想尽快从起点到达终点,那也就是求最快路径的问题了

Dijkstra算法实现最快路径_第1张图片

接下来我们先把问题建模

这是GRAPH表,将该路径描述用表格形式表现出来

Dijkstra算法实现最快路径_第2张图片

graph = {}#定义邻居表
graph["start"] = {}#起点的邻居
graph["start"]["a"] = 6
graph["start"]["b"] = 2

graph["a"] = {}#a点的邻居
graph["a"]["end"] = 1

graph["b"] = {}#b点的邻居
graph["b"]["a"] = 3
graph["b"]["end"] = 5

graph["end"] = {}#终点没有任何邻居

然后是COSTS表,用于将起点到各个点的的开销列出来,不能直接到达的,该事件设为无穷大(用“-”表示,后期再更改)

costs = {}#定义开销表,即起点到其余节点的开销,不是直接到达的,就暂时用无穷大定义
costs["a"] = 6
costs["b"] = 2
costs["end"] = float("inf")#定义极大值

最后是PARENT表,用于记录每个节点的父节点(父节点:如B被起点指向,则称起点是B的父节点)(若有某个远端节点(非起点指向)被两个节点指向,则暂时不写,用“-”表示)

parent = {}#定义父节点表,仅看只有一个父节点的节点,若有两个父节点,则暂时定义为空
parent["a"] = "start"
parent["b"] = "start"
parent["end"] = None #终点节点(非远端节点)在表中有两个父节点,故暂时不填

至此,问题描述,建模完毕

我们先定义一个列表,用于存储那些被处理的节点,防止重复处理

processed = [] #定义flag,用于标记某节点已被处理,防止多余计算甚至死循环

接下来是具体算法描述部分:

定义find_lowest_cost_node函数,传入COSTS表,用于查找当前未处理的,函数返回用时最少的下一节点,通俗点来说,就是把起点的子节点按用时情况,从小到达依次返回一个子节点(是返回一个节点,不是时间),思想是:每次定义一个无穷大,然后每次将起点的子节点遍历,直到找出此时的用时最小的节点,思想类似冒泡排序中的找出最大/小值

#此函数的作用是依次获取该起点能到的所有点,从小到大
def find_lowest_cost_node(costs):#找出到达开销最小的节点
    lowest_cost = float("inf")#定义极大值
    lowest_cost_node = None
    for node in costs:
        cost = costs[node]
        if cost < lowest_cost and node not in processed:
            lowest_cost = cost
            lowest_cost_node = node
    return lowest_cost_node

 最关键的下面的算法思想:

上一个函数将依次返回起点到另一个用时最少的节点,然后分如下几步:

         1.记录起点到该点的用时cost

         2.遍历该节点的所有邻居,分别得到该点到其各个邻居的用时(比如B的一个邻居A)

         3.在原始costs表中查询到起点到A的开销为6,就是代码中的costs[n],起点到B的开销为2(也就是步骤1中cost)B到A的开销为3,就是代码中的neighbors[n],将costs[A]与cost+neighbors[A]作比较,也就是(6与2+3作比较),后者小于前者,那么就更新路径(之前是起点直接到A,用时6,现在要想到达A,就起点先到B,然后B再到A,用时5,显然后面这条路径用时少一些,然后更新costs表和parent表)

def main():
    node = find_lowest_cost_node(costs)
    while node is not None:
        cost = costs[node]
        neighbors = graph[node]#获取该node节点的邻居
        for n in neighbors.keys():#将该节点的邻居依次遍历出来
            new_cost = cost+neighbors[n]#计算从当前节点到达其邻居的开销与其起点到其开销的和
            if costs[n] > new_cost:#如果新开销和比之前的开销小,就更新开销表和父节点表
                costs[n] = new_cost#将起点到该节点的开销更新
                parent[n] = node#更新该节点的父节点,意味着从这条路径过来花的时间最少
        processed.append(node)#将该节点标记为已处理节点
        node = find_lowest_cost_node(costs)#继续找下一个未被处理的节点
    print(costs["end"])

弗洛伊德算法:Floyd-傻子也能看懂的弗洛伊德算法(转)

你可能感兴趣的:(算法,Dijkstra)