1
0
mirror of https://gitee.com/willfree/mlsr.git synced 2026-06-15 19:24:47 +08:00

实现了迪克斯特拉算法基本计算逻辑

This commit is contained in:
free will
2022-05-12 11:55:05 +08:00
parent 808e8648f4
commit 2966fa3a42
@@ -9,6 +9,7 @@
package Calculator
import (
"math"
"mlsr/common"
"mlsr/lsa"
"mlsr/lsdb"
@@ -24,14 +25,21 @@ type LinkStateRoutingTableCalculator struct {
NO_NEXT_HOP int
// 私有变量区
// 表示源路由器想要到达某路由器,其最短路径上经过的上一个路由器。
m_parent []int
// 表示源路由器想要到达某路由器,其最短路径的距离
m_distance []uint64
EMPTY_PARENT int
INF_DISTANCE uint64
NO_MAPPING_NUM int
}
// 一些在最短路径计算时会用到的常量
const (
EMPTY_PARENT = -12345 // 没有父节点 -12345
INF_DISTANCE = math.MaxUint64 // 无限距离 2147483647
NO_MAPPING_NUM = -1 // 没有映射的点 -1
// 公用常量
NO_NEXT_HOP = -12345 // 没有下一跳 -12345
)
//
// CalculatePath
// @Description: 计算可转发路径。路由计算里的唯一Public的接口
@@ -49,25 +57,85 @@ func (c *LinkStateRoutingTableCalculator) CalculatePath(routerMap *RouterMap,
//
// doDijkstraPathCalculation
// @Description: 在邻接矩阵基础上,针对源路由器,做迪吉斯特拉计算
// 在注释中,“左集”表示已访问节点,“右集”表示未访问节点
// @receiver c
// @param sourceRouter
//
func (c *LinkStateRoutingTableCalculator) doDijkstraPathCalculation(sourceRouter int) {
// 尚未加入左集的最近元素(Q中右集最小元素)
var u int
// 每个单元代表具有该映射号的路由器。
// Q是queue首字母,它按升序存储所有路由器
Q := make([]int,c.m_nRouters)
// 尚未加入左集的最近元素在Q中的索引值
head := 0
// 初始化parent
for i := 0; i < c.m_nRouters; i++ {
// 每个点的最短路径上一点都初始化为空,即无法到达源路由器
c.m_parent[i] = EMPTY_PARENT
// 数组中第i个元素存储的是:源路由器到映射号为i的路由器之间的距离。初始化为无穷大
c.m_distance[i] = INF_DISTANCE
// 路由器队列初始化为按映射号排列
Q[i] = i
}
if sourceRouter != NO_MAPPING_NUM{
// 源路由器到其本身的距离为0
c.m_distance[sourceRouter] = 0
// 排序完毕,Q中第一个节点必然为源路由器
c.sortQueueByDistance(Q,c.m_distance,head,c.m_nRouters)
// 当我们没有访问完每一个节点时,执行循环
for head < c.m_nRouters {
// 将u设置为head当前指向的节点。“u,你就是天选之子!”
u = Q[head]
if c.m_distance[u] == INF_DISTANCE {
// 只有没有可访问的节点时,这里才会被执行。"天选之子是个废物,亡矣!"
break
}
// 对u的相邻节点进行迭代遍历。“朕要以你为衡,重设天下!”
for v := 0; v < c.m_nRouters; v++ {
// 如果u->v是可达的,
if c.adjMatrix[u][v] != route.NON_ADJACENT_COST{
// 而且我们还没有访问过v,即v属于右集,
if c.isNotExplored(Q,v,head+1,c.m_nRouters){
// 如果到这个节点的距离+从这个节点到v的距离,
// 小于我们在构建adj LSA时得到的从源节点到v的距离,
// 就更新为新距离【算法中的松弛操作】
if c.m_distance[u]+c.adjMatrix[u][v] < c.m_distance[v] {
// 设置新距离
c.m_distance[v]=c.m_distance[u]+c.adjMatrix[u][v]
// 设置parent,即我们如何到达v的
c.m_parent[v]=u
}
}
}
}
// 右移head位置,从我们所在的位置按距离重新排序列表。"苍天已死,黄天当立!"
head++
c.sortQueueByDistance(Q,c.m_distance,head,c.m_nRouters)
}
}
}
//
// sortQueueByDistance
// @Description: 对列表中的元素进行简单排序
// @Description: 对列表中的元素进行交换排序
// @receiver c
// @param Q 要排序元素的数组
// @param dist 包含距离的数组
// @param start 列表中要排序的第一个元素
// @param element 列表中要排序的最后一个元素
// @param element 列表元素数目
//
func (c *LinkStateRoutingTableCalculator) sortQueueByDistance(
Q []int,dist []uint64,start int,element int) {
for i := start; i < element; i++ {
for j := i+1; j < element; j++ {
if dist[Q[j]] < dist[Q[i]]{
temp := Q[j]
Q[j] = Q[i]
Q[i] = temp
}
}
}
}
//
@@ -77,11 +145,16 @@ func (c *LinkStateRoutingTableCalculator) sortQueueByDistance(
// @param Q 要查看的元素列表
// @param u 要检查的元素
// @param start 要查看的列表的开头
// @param element 要查看的列表的结尾
// @param element 列表元素数
//
func (c *LinkStateRoutingTableCalculator) isNotExplored(
Q []int,u int,start int,element int) int {
Q []int,u int,start int,element int) bool {
for i := start; i < element; i++ {
if Q[i]==u {
return true
}
}
return false
}
func (c *LinkStateRoutingTableCalculator) addAllLsNextHopsToRoutingTable(