我找不到适合我问题的正确答案,这就是我要问的原因。
我有一个包含uid(整数,唯一)列的Rooms表。 另外我有一个退出表,它具有fromuid(整数)touid(整数)
我想找到所有从uid到目标uid的可能出口。
rooms表具有约32000行。每个房间可以有大约10个通往其他房间的出口。
我想要获取最终到达目标uid的所有可能的行。
答案 0 :(得分:0)
这是在Lua中做到这一点的方法。
创建一个Lua表,将每个节点的出口保留为节点ID表...
exits = {}
function dbexits(db)
for fromuid, touid in db:urows('SELECT fromuid, touid from exits') do
local et = exits[fromuid] or {}
et[#et+1] = touid
exits[fromuid] = et
end
end
使用广度优先搜索来查看是否存在从fmid
到toid
的路径; seen
表可防止路径中的循环无限回归。
function pathexists (fmid, toid)
local seen = {}
local work = {fmid}
while #work > 0 do
local c = work[#work]
work[#work] = nil
seen[c] = true
if c == toid then
return true
end
for _,v in pairs(exits[c]) do
if not seen[v] then work[#work+1] = v end
end
end
return false
end
在源节点的每个出口上使用pathexists
函数以查看其是否到达目标节点...
function findexits (sourceid, targetid)
local result = {}
local srcexits = exits[sourceid]
for _,e in pairs(srcexits) do
if pathexists(e,targetid) then
result[#result+1] = e
end
end
return result
end
这是一个简单的测试:
sqlite3 = require("lsqlite3")
db = sqlite3.open_memory()
db:exec[[ CREATE TABLE exits (fromuid, touid) ]]
db:exec[[ INSERT INTO exits VALUES (1, 2) ]]
db:exec[[ INSERT INTO exits VALUES (1, 3) ]]
db:exec[[ INSERT INTO exits VALUES (2, 1) ]]
db:exec[[ INSERT INTO exits VALUES (2, 3) ]]
db:exec[[ INSERT INTO exits VALUES (3, 1) ]]
db:exec[[ INSERT INTO exits VALUES (3, 5) ]]
db:exec[[ INSERT INTO exits VALUES (4, 2) ]]
db:exec[[ INSERT INTO exits VALUES (4, 6) ]]
db:exec[[ INSERT INTO exits VALUES (5, 1) ]]
db:exec[[ INSERT INTO exits VALUES (5, 2) ]]
db:exec[[ INSERT INTO exits VALUES (6, 7) ]]
db:exec[[ INSERT INTO exits VALUES (6, 3) ]]
db:exec[[ INSERT INTO exits VALUES (7, 4) ]]
db:exec[[ INSERT INTO exits VALUES (7, 3) ]]
--[[
for row in db:nrows("SELECT * FROM exits") do
print(row.fromuid, row.touid)
end
]]--
dbexits(db)
--[[
function printf(s,...)
return io.write(s:format(...))
end
for k,v in pairs(exits) do
printf("\n%d: ", k)
for _,e in pairs(v) do
printf("%d ", e)
end
end
]]--
e = findexits(1,5)
--[[
for _,v in pairs(e) do print(v) end
]]--
assert(e[1] == 2)
assert(e[2] == 3)
e = findexits(1,4)
assert(#e == 0)
使用Lua 5.4和lsqlite3 v3.24.0通过测试