单源最短路径-Dijkstra算法

8 篇文章 0 订阅

无权图-BFS

graph = {
    1:[2,4],
    2:[4,5],
    3:[1,6],
    4:[3,5,6,7],
    5:[7],
    6:[],
    7:[6],
}

from collections import deque

dist = {}
path = {}
def bfs(graph,start): # 无权最短路径问题就是bfs算法的改进
    search = deque()
    search.append(start)
    path[start] = 0 # 源点的没有上一个结点,要特殊化
    dist[start] = 0
    while search:
        cur =search.popleft()
        for node in graph[cur]:
            if dist.get(node) is None: # 对于当前结点的邻接点,如果没有被访问过
                dist[node] = dist[cur] + 1 # 当前路径长度要+1
                path[node] = cur # 此邻接点的上一步为当前结点
                search.append(node)

bfs(graph,3) # 源点为3
print('Path:')
print(path)
print('Distance:')
print(dist)
Path:
{3: 0, 1: 3, 6: 3, 2: 1, 4: 1, 5: 2, 7: 4}
Distance:
{3: 0, 1: 1, 6: 1, 2: 2, 4: 2, 5: 3, 7: 3}

有权图-Dijkstra算法

Dijkstra

graph = {
    1:{2:2,4:1},
    2:{5:10,4:3},
    3:{1:4,6:5},
    4:{3:2,6:8,7:4,5:2},
    5:{7:6},
    6:{},
    7:{6:1},
}

def shortest_path(graph,dist,visited): # 返回未被收录顶点中dist最小者
    MinDist = float('inf')
    for node in graph: # 这里为全部遍历一遍,还可以采用最小堆
        if node not in visited and dist[node] < MinDist:
            # 若V未被收录,且dist[V]更小
            MinDist = dist.get(node)
            MinNode = node
    if MinDist < float('inf'):
        return MinNode
    else:
        return None

def Dijkstra(graph,start):
    # 初始化
    global visited,path,dist
    visited = set()
    path = {}
    dist = {}
    for node in graph:
        dist[node] = graph[start].get(node, float('inf')) 
        # 如果图中的点和当前结点不是邻接点,那么从当前结点到图中的点的dist定义为无穷大
        # 否则dist为权值
        if dist[node] < float('inf'): # 如果邻接,那么定义好路径
            path[node] = start
    # 访问源点
    visited.add(start)
    dist[start] = 0
    path[start] = -1 # 源点path特殊化
    while True:
        min_node = shortest_path(graph,dist,visited)
        if min_node is None:
            break
# 这里用下面三行实现shortest_path的功能,不过fromkeys每次都会新建一个dist
#       if len(graph) == len(visited): # 如果都被访问过,结束
#           break
#       min_node = min(dist.fromkeys(filter(lambda node:node not in visited,graph)),key=dist.get)
        visited.add(min_node) # 找到当前结点的邻接未访问的权值最小的点,访问它(使它成为当前结点)
        for node in graph: # 此循环找到
            if node not in visited and node in graph[min_node]: # 表示此节点node是当前结点的邻接点
                if graph[min_node][node] < 0: # 不能处理负值圈
                    return False
                if dist[min_node] + graph[min_node].get(node,float('inf')) < dist[node]: 
                    # 如果当前结点的dist加上当前结点到它的权值<它的dist,更新dist,path
                    dist[node] = dist[min_node] + graph[min_node].get(node,float('inf'))
                    path[node] = min_node
    return True

print(Dijkstra(graph,1))
print('path',path)
print('dist',dist)
True
path {2: 1, 4: 1, 1: -1, 3: 4, 5: 4, 6: 7, 7: 4}
dist {1: 0, 2: 2, 3: 3, 4: 1, 5: 3, 6: 6, 7: 5}
### 回答1: Dijkstra算法是一种用于解决单源最短路径问题的算法。它的基本思想是从起点开始,逐步扩展到其他节点,每次选择当前距离起点最近的节点,并更新与该节点相邻的节点的距离。通过这种方式,可以找到起点到其他节点的最短路径。Dijkstra算法的时间复杂度为O(n^2),但是可以通过使用堆优化来将其优化到O(nlogn)。 ### 回答2: Dijkstra算法是一种解决单源最短路径问题的贪心算法,其思想是利用“松弛”操作来不断更新当前点到源点的最短距离,但前提是所有边的权重非负。如果有负权边,则需要使用Bellman-Ford算法。 首先,我们需要定义一个数组dis数组,用于存储源点s到各个点的最短距离。dis[s]初始为0,其他点初始为无限大。接着,我们需要维护一个集合S,表示已经求出最短路径的点的集合。将源点s加入集合S中。 对于每个未加入S的点v,我们通过选择其它点到源点s的最短路径中的一个点u,然后将dis[v]更新为dis[u] + w(u,v),其中w(u,v)表示边(u,v)的权重。具体地,这个操作称为“松弛”操作。 在松弛操作中,我们需要比较dis[u] + w(u,v)和dis[v]的大小,如果前者更小,则更新dis[v]的值为dis[u] + w(u,v)。 重复执行以上操作,直到所有的点都加入到集合S中。最后dis数组中存储的就是源点s到所有点的最短距离。 Dijkstra算法可以用堆优化,时间复杂度为O(mlogn),其中n表示图中的点数,m表示边数。Dijkstra算法也可以应用于稠密图,时间复杂度为O(n^2)。 总之,Dijkstra算法是一种经典的求解单源最短路径问题的算法,其实现简单,效率高,被广泛应用于路由算法和图像处理等领域。 ### 回答3: Dijkstra算法是一种在加权有向图中寻找从源节点到其他节点的最短路径的贪心算法。该算法基于其它路径加权节点的已知最短路径去更新更长路径的信息直到找到从源节点到目标节点的最短路径。在整个计算过程中,Dijkstra算法需要维护一个待处理节点集合和一个距离源节点的最短路径数组。 算法的具体实现如下: 1. 初始化源节点及其距离为0,其他节点的距离为无穷大。 2. 将源节点加入到待处理节点集合中。 3. 对于源节点的所有相邻节点,更新它们距离源节点的最短路径。如果当前路径小于之前已知的最短路径,则更新最短路径数组。 4. 遍历待处理节点集合中除源节点外的节点,选择距离最近的节点作为当前节点,并将它从待处理机集合中移除。 5. 对于当前节点的所有相邻节点,更新它们距离源节点的最短路径。如果当前路径小于之前已知的最短路径,则更新最短路径数组。 6. 重复步骤4和5,直到待处理节点集合为空或者目标节点已经被遍历。 Dijkstra算法的时间复杂度为O(n^2),其中n为节点数,由于它是贪心算法,只能处理非负权重的图,否则可能会陷入死循环。但是,Dijkstra算法单源最短路径问题的最优解,因此在处理小规模的图时效果很好。在处理大规模图时,需要使用其他高效的算法,如A*算法、Bellman-Ford算法等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值