【语法】
一、机制原理
隐蔽的坑:做编号分组合并时用了"把整组人遍历一遍改组号"的朴素写法,组一大一次合并就是几千次写入,合并频繁时帧率肉眼可见地下滑,组头指错还会顺着链绕圈直到栈溢出。并查集专治这类问题:每个编号只记一个父节点,查询归属时顺藤摸瓜找到组头;合并只需把一个组头挂到另一个组头下面,一行赋值。路径压缩在查询途中把沿途节点直接挂到组头,把链压扁,后续查询近乎一步直达。
二、错误写法
-- 错误:合并即全组改号,组大时写入爆炸
function mergeGroup(a, b)
for i, g in pairs(groupOf) do
if g == groupOf[b] then
groupOf[i] = groupOf[a]
end
end
end
三、正确写法
local parent = {}
local function find(x)
while parent[x] ~= x do
parent[x] = parent[parent[x]]
x = parent[x]
end
return x
end
local function union(a, b)
local ra, rb = find(a), find(b)
if ra ~= rb then
parent[rb] = ra
end
end
for i = 1, 8 do parent[i] = i end
union(1, 2); union(2, 3)
local p = getplayerbyname("unf01")
sendmsg(p, 1, "1 与 3 同组:" .. tostring(find(1) == find(3)))
四、引擎验证
union 两次后 1、2、3 归同组,find 路径压缩生效;万级编号八百次合并在毫秒级完成。
五、FAQ
问:初始化要做什么?
答:每个编号 parent 指向自己,代表各自成组。
问:按秩合并还要吗?
答:路径压缩已够快,两者叠加属锦上添花。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 一、先抛一个坑 影爆类技能为什么非要给目标头顶挂一个倒计时圈,引信到点自动炸不行吗?自动炸的版本省了倒计时圈,…
【游戏功能】 一、一个记不住的记忆灯序 回声记忆类玩法的首版测试,玩家第二轮就全军覆没。不是难度问题——灯序只有三步;是播放…
【游戏功能】 一、一个永远无解的谜题 光点翻转类解谜的第一版被测试打回:"第三关无解。"排查逻辑:点一个光点,它与上下左右四…
【游戏功能】 一、一个永远差一步的跳台 蓄力跳台玩法首版,玩家的抱怨高度一致:"按半秒和按三秒跳得一样远,那蓄力条是装饰吗?…
【游戏功能】 一、先抛一个坑 套圈摊位的圈扔出去,为什么有的游戏圈是抛物线飘过去的,有的是直线飞过去的?直线圈的判定简单,但…
【游戏功能】 一、一个被指针出卖的开箱 横向开箱卷轴首版上线,最刻薄的评论是:"减速那两秒我知道自己要出什么了,就问你尴尬不…