Microcity——lua语言编写Dijkstra算法与Floyd算法求解航线网络图最短路

Microcity是大连海事大学交通运输工程学院的孙卓教授自主开发的一款集3D仿真、空间数据分析等众多功能于一体的软件。本文使用lua语言,利用Microcity软件进行编译,分别使用Dijkstra与Floyd两种算法对拓扑化后的航线网络图求解最短路径。

拓扑化后的航线网络图:

部分路段ID、起点ID、终点ID、实际路长数据:

 


一、Dijkstra算法计算从起点到各点的最短路代码

Links=GetControl("links.shp")
Nodes=GetControl("nodes.shp")
marked={}
stpdis={}			
preid={}
startid=1                                  --本例设置起点为1
a={}
for inodes0 = 1, GetRecCount(Nodes) do   --数组初始化
    id0 = GetValue(Nodes,"ID",inodes0)
    marked[id0]	= false					 --标记数组
    stpdis[id0]	= 100000000				 --最短距离
    preid[id0]	= -1					 --前溯节点号
end
crtid = startid					         --设置当前节点为起点
marked[crtid] = true
stpdis[crtid] = 0
judge = false                            --设置判断变量
while not judge do	                     --判断变量(存在未永久标号的点)
    for ilinks = 1, GetRecCount(Links) do 			--搜索所有路段
        linko = GetValue(Links, "O", ilinks)		--得到路段起点
        linkd = GetValue(Links, "D", ilinks)		--得到路段终点
        linkdis = GetValue(Links, "W", ilinks)
        if linko == crtid then		        --如果与当前节点邻接
            tmpid = linkd				
            if stpdis[crtid] + linkdis < stpdis[tmpid] then      --并且另一端点的最短距离较大
                stpdis[tmpid] = stpdis[crtid] + linkdis
                preid[tmpid] = crtid		--修改另一端点的最短距离和前溯节点
            end
        elseif linkd == crtid then
            tmpid = linko
            if stpdis[crtid] + linkdis < stpdis[tmpid] then      --并且另一端点的最短距离较大
                stpdis[tmpid] = stpdis[crtid] + linkdis
                preid[tmpid] = crtid		--修改另一端点的最短距离和前溯节点
            end
        end
    end
    for inodes1 = 1, GetRecCount(Nodes) do
        id1 = GetValue(Nodes,"ID",inodes1)
        judge = true                       
        if not marked[id1] then            --若不存在未永久标号的点,判断变量变为true,此时所有点都已得到永久标号,跳出本循环,不进入下一个if语句并跳出while大循环
            judge = false                  --若存在未永久标号的点,判断变量仍为false
            crtid = id1                    --设置下一个当前节点暂时为该未永久标号的点
            break
        end
    end
    if not judge then
        for inodes2 = 1, GetRecCount(Nodes) do 		--搜索所有节点
            id2 = GetValue(Nodes,"ID",inodes2)
            if not marked[id2] and stpdis[id2] < stpdis[crtid] then		            --找到未标记的有最小距离的节点
                crtid = id2				        --重新设置当前节点
            end
        end
        marked[crtid] = true			        --标记新的当前节点
    end
end
for inodes3 = 1, GetRecCount(Nodes) do
    id3 = GetValue(Nodes,"ID",inodes3)
    Print("destination point",id3,":",stpdis[id3])  --输出当前点及到其最短距离
    n = 1
    id = id3
    while id ~= startid do              --倒序存储
        a[n] = preid[id]
        id = preid[id]
        n = n+1
    end
    while n ~= 1 do                     --正序输出
        Print(a[n-1])
        n = n-1
    end
    Print(id3)
end

二、Floyd算法计算从各点到各点的最短路代码

Links = GetControl("links.shp")
Nodes = GetControl("nodes.shp")
N = GetRecCount(Nodes)
L = GetRecCount(Links)
--初始化距离矩阵dis和前置跳转点矩阵path
--由于航线图左右侧同一点连通,需设置两个判断变量处理矩阵
judge1 = {}
judge2 = {}
for i = 1, N do
    id = GetValue(Nodes, "ID", i)
    judge1[id] = true  --大循环的判断变量1初始化
end
num = 0
dis = {}  
path = {}
for i1 = 1, N do
    id1 = GetValue(Nodes, "ID", i1)
    --每次大循环都需将小循环的判断变量2重新初始化
    for i0 = 1, N do
        id0 = GetValue(Nodes, "ID", i0)
        judge2[id0] = true
    end
    --若大循环的判断变量1为true(即未检索过该id)才会继续处理
    if judge1[id1] then
        dis[id1] = {}
        path[id1] = {}
        for i2 = 1, N do
            id2 = GetValue(Nodes, "ID", i2)
            --若小循环的判断变量2为true(即未检索过该id)才会继续处理
            if judge2[id2] then
                if id1 == id2 then         --各点到自己的矩阵处理
                    dis[id1][id2] = 0
                    path[id1][id2] = id2
                else                       --各点到其它点的矩阵处理
                    dis[id1][id2] = 1000000  --初始设为无穷大
                    path[id1][id2] = id2
                end
                judge2[id2] = false --若小循环已检索该点,更新判断变量2
            end
        end
        judge1[id1] = false --若大循环已检索该点,更新判断变量1
        num = num + 1       --求得最终共有几个不重复id的点(即矩阵的行数或列数)
    end
end
--输入航线图的路段距离
for linki = 1, L do
    o = GetValue(Links, "O", linki)			--得到路段起点
	d = GetValue(Links, "D", linki)			--得到路段终点
    w = GetValue(Links, "W", linki)         --得到路段距离
    dis[o][d] = w   --无向图处理
    dis[d][o] = w   --无向图处理
end
--Floyd算法核心步骤
for k = 1, num do         --中间点循环
    for v = 1, num do     --起点循环
        for w = 1, num do --终点循环
            if dis[v][w] > (dis[v][k] + dis[k][w]) then  
                dis[v][w] = dis[v][k] + dis[k][w]--更新距离矩阵dis
                path[v][w] = path[v][k]          --更新前置跳转点矩阵path
            end
        end
    end
end
--输出最短距离
for i = 1, num do
    for j = 1, num do
        Print(i,"到",j,"的最短路长为:",dis[i][j])
    end
end
--输出最短距离经过路径(以1为起点将结果与迪杰斯特拉算法结果对比)
v = 1
for i = 1, num do
    w = i
    k = path[v][w]
    Print(v,"到",w,"的最短路径为:")
    Print(v)
    while k ~= w do    --搜索前置跳转点矩阵直至终点
        Print(k)
        k = path[k][w]
    end
    Print(w)
end


结果对比:Dijkstra算法适合求解单源最短路问题,Floyd算法适合求解多源最短路问题。除此之外,计算最短路径的算法还有Bellman-Ford算法、SPFA算法、A*算法等等。

Microcity下载链接:https://microcity.github.io

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值