Lua中如何快速实现队列?

9
我正在使用Lua制作游戏,并需要使用广度优先搜索算法来实现快速的路径查找,以便在敌方AI和玩家之间找到最短路径。
我将同时使用最多3个敌人来使用此算法,地图是一个二维基于瓷砖的迷宫。我已经实现了碰撞检测,现在要做的就是让敌人找到通向玩家的最短路径,以一种能够快速完成且每秒钟每个敌人可以处理80-90次的方式。
以前我使用C ++中的队列实现了广度优先搜索。从我所读到的关于Lua的内容来看,使用表格实现的堆栈非常高效,因为元素在进行push()(即table.insert)和pop()(即table.remove)操作后不需要进行移位。然而,我推测,具有大容量的队列在Lua中可能非常低效,因为如果您想从表格的索引1插入/删除某些内容,则必须将表格中的所有其他元素向上或向下移动。
因此,我想问一些对Lua有经验的人一些简单的问题。这种语言中最简单和/或最快的队列实现是什么?在Lua中是否可能拥有快速的队列,还是通常认为Lua将始终被迫对队列操作(如pop()或append())进行“移位”?
编辑:我了解到Lua表格中“移位元素”的底层实现是用C编写的,因此非常优化。我只是想知道在开始编写简单的表格实现之前是否有更好的队列选项。
1个回答

16

在Lua中,快速实现队列(实际上是双向队列)的方法可以参考Lua编程(Programming in Lua)一书:

List = {}
function List.new ()
  return {first = 0, last = -1}
end

它可以在常数时间内在两端插入或删除元素,关键是存储firstlast

function List.pushleft (list, value)
  local first = list.first - 1
  list.first = first
  list[first] = value
end

function List.pushright (list, value)
  local last = list.last + 1
  list.last = last
  list[last] = value
end

function List.popleft (list)
  local first = list.first
  if first > list.last then error("list is empty") end
  local value = list[first]
  list[first] = nil        -- to allow garbage collection
  list.first = first + 1
  return value
end

function List.popright (list)
  local last = list.last
  if list.first > last then error("list is empty") end
  local value = list[last]
  list[last] = nil         -- to allow garbage collection
  list.last = last - 1
  return value
end

12
原文:Turns out I just put one on GitHub two days ago that's usable as a library. I deal with indices slightly differently but otherwise it's the same thing. MIT license (not in the repo yet but I will add it tonight), feel free to use it :) https://github.com/catwell/cw-lua/tree/master/deque翻译:原来我在两天前在GitHub上发布了一个可用作库的东西。我的索引处理略有不同,但其他方面是一样的。采用MIT许可证(尚未在该仓库中添加,但我今晚会添加),请随意使用 :) https://github.com/catwell/cw-lua/tree/master/deque - catwell
@catwell 请记住,如果您在弹出操作后将其用作FIFO队列而不进行旋转,则这是一个定时炸弹,因为队列的内容将始终沿着数字范围向上或向下移动。虽然单个浮点数的理论数值限制大约为10^38,因此相当安全,但尾数只有23位(约为10^6),这意味着在这些位之后,分辨率会降低(10^20 + 1 = 10^20)。 - dualed
1
@dualed 实际上,Lua 数字默认为双精度浮点数,因此只有在 2^52(介于 10^15 和 10^16 之间)以上才会出现这种行为。在我看来,这仍然非常高。如果您每秒执行一百万次操作,那么直到超过 140 年才会成为问题...请注意,如果使用 32 位整数,则情况会更糟。 - catwell
@catwell 嗯,我一直以为Lua使用单精度浮点数,但手册也说双精度是默认值。现在我不知道自己从哪里得到这个想法了...所以,你是对的,如果使用双精度浮点数,任何应用程序都不太可能运行足够长的时间而导致崩溃,抱歉。 - dualed
4
你介意展示一下调用这些函数和初始化列表/队列的实现方式吗? - Timothy Swan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接