首页 > 代码库 > Program in Lua中图算法的改进(打印所有图路径)
Program in Lua中图算法的改进(打印所有图路径)
在Program in Lua第二版,第11.7节中介绍了用lua写“图”数据结构的方法,
但书中提供的图的算法只能打印出第一条找到的正确路径,于是我就自己琢磨
着怎么用lua写出一个图算法打印出所有可能的路径,自己独自一个人思考了
很久,期间没有参考任何资料,完全靠“头脑暴力”把它解决了,最后思考了看看,
也不知道这到底是什么算法,完全凭借着自己认为的所谓的"退化"的概念,奇妙
的解决了这个问题,所以我把这个算法拿出来分享一下。
(总觉得在哪本书上看到过“退化”这个字眼,但我其实不知道什么是真正的“退化”,
但在我脑海里,“退化”就是一个概念而已,在这里,觉得似乎用这个概念有那么
一点合适的味道,那我就把它称之为“退化”了。另外,也许这个算法也有人实现
过,但我其实并不知道这是什么算法,我只知道这个算法的思想---用我所谓的
“退化”(因为我学的很少,至少还没去专门学过图论,所以勿喷),如果我这个
”设计“的算法你见过,或知道是什么算法可以告诉我(至少我不认为我能想出来
的东西别人会没想到,我应该还没到那种境界吧=_=))
正文:
首先是一个保存了图中数据的.lua文件,其名为graph.lua,
相对路径为./lua/graph.lua
内容如下所示:
a b b c b f c d c f d e f g g h f i i j j c j k i l c k k l
示意图如下:
(该算法只适用于单向的图)
然后是“图”数据结构及我“设计”的这个算法:
相对路径为./lua/11.7.lua
(注释写的很详细,都写在代码里面了,不懂的可以问我)
Graph = {} --生成图节点 function Graph.newNode(graph, name) if not graph[name] then graph[name] = {name = name, adj={}} --创建一个新的图结点 end return graph[name] end --生成图 function Graph.gen(s) local graph = {} for line in io.lines(s) do --匹配起始,通往结点 local namefrom, nameto = string.match(line, "(%S+)%s(%S+)") local from = Graph.newNode(graph, namefrom) --生成起始结点 local to = Graph.newNode(graph, nameto) --生成通往结点 local path = from.adj --得到路径表 path[#path + 1] = to --连接图结点路径 end return graph end function Graph.findpath(curr, to, path, visited) --参数:当前结点, 目的结点, 保存路径的集合, 已访问结点集合(可退化) --关于退化:这里的退化概念是自己提出的,意思是对得到一条通路上的结点 --往前回溯取消记录,以致于另一个递归搜素分支可以找到这条路径,同时, --对于已压栈函数记录的结点和无通路径上的结点保存记录以至于递归函数 --直接返回 path = path or {} --path作为table来记录所有保存的路径 visited = visited or {} --visited为保存记录结点的表 if visited[curr] then --对记录结点直接返回 return nil end visited[curr] = true --记录访问节点 path["name"] = curr["name"] --记录路径 if curr == to then --找到终点,构成一条路径,返回 visited[curr] = nil --退化(取消该终点的记录) return path end local p for i,from in ipairs(curr.adj) do path[i] = {father = path} --保存一个能找到父结点的字段 --递归搜索路径 local rightPath = Graph.findpath(from, to, path[i], visited) if not rightPath then path[i] = nil end --找不到,取消一个子table p = rightPath or p --有路径时记录最后一条通路返回,否则返回nil end if p then visited[curr] = nil --退化该路径节点 return p["father"] --返回该路径的father,即本结点 end path = nil --没找到,删除该节点 end --打印所有图路径 function Graph.printPath(path, visited) --路径结点集合, 已访问结点集合(可退化) path = path or {} visited = visited or {} if path then visited[#visited + 1] = path --以数组形式保存访问过的路径 io.write(path.name, " ") --打印本结点名字和空格符 end local maxn = table.maxn(path) --取可行支路中的最大编号 if maxn == 0 then --不存在支路(即终点)时 visited[#visited] = nil --退化,取消记录该结点 io.write("\n") --该条路径已完全输出,换行 return end --终点,返回 local count = 0 --统计支路的数目 for i = 1, maxn do if path[i] then --该条编号的支路存在 count = count + 1 --递增支路数 if count > 1 then --除第一条支路之外, for i,v in ipairs(visited) do --对已记录的根路结点进行打印 io.write(v.name, " ") end end Graph.printPath(path[i], visited) --然后再次递归搜索下一条支路 end end visited[#visited] = nil --支路已搜索完毕,此分支不再搜索,退化 end local graph = Graph.gen("./lua/graph.lua") --生成图 local path = Graph.findpath(graph["a"], graph["l"]) --寻找图路径 Graph.printPath(path) --输出图路径
下面是运行后的输出结果:
Program in Lua中图算法的改进(打印所有图路径)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。