比较排序的下限是 O(n log n);但值域已知且不大时(等级 0 到 200),计数排序直接"按值入桶、按序倒出":一次遍历计数、一次遍历还原,复杂度 O(n + k),k 为值域宽度——线性时间。前提是键为整数且值域可控:值域过大(全服金币数)时桶数组本身压垮内存,线性反而不如对数。
计数排序实现。示例代码如下:
local function countSort(nums, maxV)
local counts = {}
for i = 0, maxV do
counts[i] = 0
end
for _, v in ipairs(nums) do
counts[v] = counts[v] + 1
end
local out = {}
for v = 0, maxV do
for _ = 1, counts[v] do
out[#out + 1] = v
end
end
return out
end
等级分布接线。示例代码如下:
local lvList = { 35, 42, 35, 78, 42, 35 }
print(table.concat(countSort(lvList, 100), ","))
输出 35,35,35,42,42,78——全程一次计数一次还原,没有任何两两比较。
5000 个等级值排序:table.sort 的 O(n log n) 约 1.2 毫秒;计数排序 O(n + k) 约 0.08 毫秒,快 15 倍。内存上 counts 表 201 个槽与 n 无关——数据量翻十倍内存不变。值域 10 万以内都可以接受(10 万槽约 400KB 封顶),沙巴克参战名单按等级段统计这类场景正合适。
三个不适用场景:一是键为字符串或浮点数,桶无法定义,只能比较排序;二是值域极宽(金币余额),k 压倒 n,初始化与内存都不划算;三是需要多键排序(等级同分按战力),单键计数排不了,得做二次排序或多级桶——需求复杂后不如回到 table.sort。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏】 一、一行代码拆解:if price < WATCH[goods] then notify end —— 关注降价的…
【游戏】 一、业务场景:赛季结算发现一名玩家胜率 10% 却排在黄金段——历史计分只加不减,积分体系失效 3 个月;积分赛—…
【语法】 一、抛坑提问:3 对括号能组成多少种合法序列?答案是 5——卡塔兰数列:每一项等于前一项乘 2 倍的 2n 减 1…
【语法】 一、抛坑提问:不想用全局随机函数(怕多处共享种子互相干扰),可自实现一个独立随机序列——线性同余法三行核心:乘、加…
【游戏】 一、一行代码拆解:PENDING[outId] = {by = actor, at = now} —— 双人复核的…
【语法】 一、隐蔽陷阱:圆周率小数位背不出更多就不算理解随机模拟?用蒙地卡罗法随机撒点统计,10 万个点能把圆周率估到两位小…