IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> networkx图论贝尔曼-福特Bellman Ford Algorithm最短路径,Python -> 正文阅读

[数据结构与算法]networkx图论贝尔曼-福特Bellman Ford Algorithm最短路径,Python

(1)Bellman Ford Algorithm,贝尔曼-福特算法,图中搜索遍历最短路径的一种适应性强的算法。Bellman Ford Algorithm可以应用在负值边权的图,这和dijkstra最短路径算法有差异,dijkstra不适应于存在负边权的图。Bellman Ford Algorithm是一种广度优先搜索最短路径策略。经过全部迭代后,每一个节点中保存的权值(node weight),即为从起始点(一般为0)到该节点的最小路径值。

(2)Bellman Ford Algorithm在迭代开始时候,选一个顶点V,然后在队列Q中保存与顶点V相邻接的节点,并更新相邻接的节点权值。但是,要特别注意,所谓在队列Q中保存与顶点相邻接的节点,只发生在相邻接的节点权值更新时候才保存,否则该邻接节点不加入队列Q。

比如,顶点V节点权值为5,从V(from_node)出发,与V相邻接的节点有V1,V2(这两个为 to_node)。假设V1当前权值为8,V与V1邻接的边权(edge_weight)为1,5+1=6 < 8,于是更新V1的节点权值(node_weight)为最新的6,并同时把节点V1加入队列Q。假设V2当前节点权值为6,V与V2邻接的边权(edge_weight)为4,5+4=9 > 6,所以V2节点权值不予更新,仍为6,且V2节点不能加入队列。

(3)每迭代一轮,删掉队列最左边(头部)的节点。

import random

import networkx as nx
import matplotlib.pyplot as plt

WEIGHT = 'weight'


def my_graph():
    G = nx.gnm_random_graph(n=8, m=10)

    pos = nx.spring_layout(G)
    nx.draw_networkx(G, pos,
                     node_color='green',
                     node_size=300,
                     font_size=10,
                     font_color='white',
                     edge_color='gray',
                     width=1,
                     with_labels=True)

    # 每条边增加随机权值
    for e in G.edges(data=True):
        e[2][WEIGHT] = random.randint(1, 9)

    my_edge_labels = nx.get_edge_attributes(G, WEIGHT)
    nx.draw_networkx_edge_labels(G, pos, edge_labels=my_edge_labels)

    for n in G.nodes():
        G.nodes[n][WEIGHT] = float('inf')

    V = 0
    G.nodes[V][WEIGHT] = 0

    print('G.edges(data=True)', G.edges(data=True))
    print('G.nodes(data=True)', G.nodes(data=True))

    bellman_ford_algorithm(G, V)

    plt.show()


# 基于队列,广度搜索遍历,贝尔曼-福特算法
def bellman_ford_algorithm(G, V):
    Q = [V]

    while True:
        if len(Q) == 0:
            break
        print('-----')
        print('Q-', Q)

        visit_node = Q[0]
        print('访问', visit_node)
        neighbors = nx.neighbors(G, visit_node)
        for to_node in neighbors:
            update_weight(G, visit_node, to_node, Q)

        del (Q[0])

        print('Q--', Q)

    print('nodes', G.nodes(data=True))

    path = find_short_path(G, 5)
    print('path', path)


# 寻找从0节点到v的最短路径
def find_short_path(G, v):
    path = [v]

    loop_flag = True
    while loop_flag:
        v_node_weight = G.nodes[v][WEIGHT]
        ok_node = None

        for from_node in nx.neighbors(G, v):
            from_node_weight = G.nodes[from_node][WEIGHT]
            edge_weight = G.get_edge_data(u=from_node, v=v)[WEIGHT]
            if (from_node_weight + edge_weight) == v_node_weight:
                ok_node = from_node
                break

        if ok_node != None:
            path.append(ok_node)
            if ok_node == 0:
                loop_flag = False
            else:
                v = ok_node

    list.reverse(path)
    return path

def update_weight(G, from_node, to_node, Q):
    form_node_weight = G.nodes[from_node][WEIGHT]
    edge_weight = G.get_edge_data(u=from_node, v=to_node)[WEIGHT]
    to_node_weight = G.nodes[to_node][WEIGHT]
    sum_weight = form_node_weight + edge_weight
    if (sum_weight) < to_node_weight:
        G.nodes[to_node][WEIGHT] = sum_weight
        Q.append(to_node)


if __name__ == '__main__':
    my_graph()

生成图:

运行日志:

G.edges(data=True) [(0, 4, {'weight': 7}), (0, 2, {'weight': 3}), (0, 6, {'weight': 2}), (1, 2, {'weight': 5}), (2, 3, {'weight': 6}), (2, 4, {'weight': 8}), (3, 5, {'weight': 2}), (4, 5, {'weight': 8}), (4, 6, {'weight': 5}), (6, 7, {'weight': 8})]
G.nodes(data=True) [(0, {'weight': 0}), (1, {'weight': inf}), (2, {'weight': inf}), (3, {'weight': inf}), (4, {'weight': inf}), (5, {'weight': inf}), (6, {'weight': inf}), (7, {'weight': inf})]
-----
Q- [0]
访问 0
Q-- [4, 2, 6]
-----
Q- [4, 2, 6]
访问 4
Q-- [2, 6, 5]
-----
Q- [2, 6, 5]
访问 2
Q-- [6, 5, 3, 1]
-----
Q- [6, 5, 3, 1]
访问 6
Q-- [5, 3, 1, 7]
-----
Q- [5, 3, 1, 7]
访问 5
Q-- [3, 1, 7]
-----
Q- [3, 1, 7]
访问 3
Q-- [1, 7, 5]
-----
Q- [1, 7, 5]
访问 1
Q-- [7, 5]
-----
Q- [7, 5]
访问 7
Q-- [5]
-----
Q- [5]
访问 5
Q-- []
nodes [(0, {'weight': 0}), (1, {'weight': 8}), (2, {'weight': 3}), (3, {'weight': 9}), (4, {'weight': 7}), (5, {'weight': 11}), (6, {'weight': 2}), (7, {'weight': 10})]
path [0, 2, 3, 5]

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-11-10 12:39:06  更:2021-11-10 12:40:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:33:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码