Program in Lua中图算法的改进(打印所有图路径)
来源:互联网 发布:cmd怎么ping端口 编辑:程序博客网 时间:2024/04/29 04:56
在Program in Lua第二版,第11.7节中介绍了用lua写“图”数据结构的方法,
但书中提供的图的算法只能打印出第一条找到的正确路径,于是我就自己琢磨
着怎么用lua写出一个图算法打印出所有可能的路径,自己独自一个人思考了
很久,期间没有参考任何资料,完全靠“头脑暴力”把它解决了,最后思考了看看,
也不知道这到底是什么算法,完全凭借着自己认为的所谓的"退化"的概念,奇妙
的解决了这个问题,所以我把这个算法拿出来分享一下。
(总觉得在哪本书上看到过“退化”这个字眼,但我其实不知道什么是真正的“退化”,
但在我脑海里,“退化”就是一个概念而已,在这里,觉得似乎用这个概念有那么
一点合适的味道,那我就把它称之为“退化”了。另外,也许这个算法也有人实现
过,但我其实并不知道这是什么算法,我只知道这个算法的思想---用我所谓的
“退化”(因为我学的很少,至少还没去专门学过图论,所以勿喷),如果我这个
”设计“的算法你见过,或知道是什么算法可以告诉我(至少我不认为我能想出来
的东西别人会没想到,我应该还没到那种境界吧=_=))
正文:
首先是一个保存了图中数据的.lua文件,其名为graph.lua,
相对路径为./lua/graph.lua
内容如下所示:
a b b cb f c dc fd ef gg hf ii jj cj ki lc k k l
示意图如下:
(该算法只适用于单向的图)
然后是“图”数据结构及我“设计”的这个算法:
相对路径为./lua/11.7.lua
(注释写的很详细,都写在代码里面了,不懂的可以问我)
Graph = {}--生成图节点function Graph.newNode(graph, name)if not graph[name] thengraph[name] = {name = name, adj={}} --创建一个新的图结点endreturn 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 --连接图结点路径endreturn graphendfunction 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 pfor 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 --找不到,取消一个子tablep = rightPath or p --有路径时记录最后一条通路返回,否则返回nilendif 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, " ") --打印本结点名字和空格符endlocal 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, " ")endendGraph.printPath(path[i], visited) --然后再次递归搜索下一条支路endendvisited[#visited] = nil --支路已搜索完毕,此分支不再搜索,退化endlocal graph = Graph.gen("./lua/graph.lua") --生成图local path = Graph.findpath(graph["a"], graph["l"]) --寻找图路径Graph.printPath(path)--输出图路径
下面是运行后的输出结果:
1 0
- Program in Lua中图算法的改进(打印所有图路径)
- 【算法题】打印二元查找树中元素和等于指定数的所有路径
- 【算法题】打印二元查找树中元素和等于指定数的所有路径
- 打印无权无向图的所有最短路径
- 【算法-java】打印出二叉树中结点值的和为输入整数的所有路径
- 算法-计算无向图中两个节点之间所有的路径
- 无向连通图中两点间所有路径的算法
- 图算法之求两点之间的所有路径(java)
- 回转顺序打印矩阵的改进算法
- 打印二叉树中路径和为某一值的所有路径
- 有向图中打印所有的环路
- SPFA:改进的BellmanFord求单源最短路径算法
- 对有向图的环的判定,并且输出图中所有的路径 C++算法
- 打印二叉树的所有路径
- 打印二叉树所有的路径
- 打印两点间的所有路径
- 打印二叉树的所有路径
- 打印二叉树所有的路径
- javax.servlet.FilterConfig翻译
- jquery 获取网页地址参数值
- 第十四周项目三
- 大数据成为监控腐败的第三只眼
- Android 性能分析案例
- Program in Lua中图算法的改进(打印所有图路径)
- JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解
- PLSQL开发笔记和小结
- Struts2和springMVC的区别
- 【官网翻译】Android屏幕适配从原理到最佳实践(很全的教程)
- SQlite3数据库的安装与使用
- 文件的压缩与解压XZip,XUnzip
- OS开发UI篇—UITableview控件简单介绍
- linux中文件描述符fd和文件指针flip的理解