算法:贝尔曼-福特算法

算法:贝尔曼-福特算法

1.简介

贝尔曼-福特算法(Bellman–Ford algorithm)是一个查找最短路径算法主要优点是支持负权重,但时间复杂度较高,还会有负权环的问题。
如果不需要权重应该使用广度优先或深度优先算法,如果只需要权重没有负权重,应该使用迪杰斯特拉算法,上面三种算法性能都会比贝尔曼-福特算法好很多。

2.图示

从A去D点路线,A->B->C->D

simple

负权环问题

正常情况下A->B->C->D的权重是3,是最近的一条路线。但是如果碰到下面这种情况就会出现回路问题,A->B->C->D时没有问题,下面还会一直D->B->C->D转圈,每转一圈权重就降1出现回路。算法最后需要检查是否出现回路。

回路

3.演示

package main

import (
	"fmt"
	"math"
)

func main() {
	graph := make(map[string]map[string]float32)
	graph["A"] = map[string]float32{
		"B": 5,
		"C": 0,
	}
	graph["B"] = map[string]float32{
		"C": -7,
	}
	graph["C"] = map[string]float32{
		"D": 5,
	}
	graph["D"] = map[string]float32{
	}
	distance, parent := bellmanFord(graph, "A")
	fmt.Println(distance)
	fmt.Println(parent)
}

func bellmanFord(graph map[string]map[string]float32, source string) (distance map[string]float32, parent map[string]string) {
	distance = make(map[string]float32)
	parent = make(map[string]string)
	// 添加当前点到所有节点权重
	// 权重为默认类型最大值
	for fromName := range graph {
		distance[fromName] = math.MaxFloat32
		parent[fromName] = ""
	}
	// 设置自身到自身的权重
	distance[source] = 0

	for i := 0; i < len(graph)-1; i++ {
		for fromName := range graph {
			for toName, weight := range graph[fromName] {
				currentWeight := distance[fromName] + weight
				if distance[toName] > currentWeight {
					// 记录最短距离 > 启始到父节点距离 + 父节点到当前子节点距离
					distance[toName] = currentWeight
					parent[toName] = fromName
				}
			}
		}
	}

	// 负权环检查
	for fromName := range graph {
		for toName := range graph[fromName] {
			if distance[toName] > distance[fromName] + graph[fromName][toName] {
				return nil, nil
			}
		}
	}
	return
}

4.参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yimtcode

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值