排行榜:
key:玩家名字,val:玩家的数值
1 local key1 = {"a1", "a2", "b1", "b2", "a3"} 2 local val1 = {1, 3, 5, 7, 9} 3 local key2 = {"b1", "a1", "a2", "b2"} 4 local val2 = {2, 4, 6, 8}
val1:原排行榜中的数值,已排序(从小到大)
key1:原排行榜val已排序的数值对应的名字
key2, val2为新的数据,两组数据合并为一组,相同名字的数值合并取最小(或最大)
采用归并排序
迭代法步骤:
1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4. 重复步骤3直到某一指针达到序列尾
5. 将另一序列剩下的所有元素直接复制到合并序列尾
递归法
原理如下(假设序列共有n个元素):
- 将序列每相邻两个数字进行归并操作,形成个序列,排序后每个序列包含两个元素
- 将上述序列再次归并,形成个序列,每个序列包含四个元素
- 重复步骤2,直到所有元素排序完毕
动态图:
又因旧排行榜数据和新排行榜数据已经是两个已经有序的数列,就不用再分了。但需要合并相同名字的数据只保留一份
使用协程合并:
1 local keys, vals = {}, {} 2 -- 创建协程 3 local function createCo(keys, values) 4 return coroutine.create( 5 function () 6 for i, v in ipairs(values or {}) do 7 coroutine.yield(keys[i], v) 8 end 9 end 10 ) 11 end 12 -- 插入到结果中并唤醒协程 13 local function insertResultAndResume(key, val, co) 14 for _, v in next, keys do 15 if v == key then 16 return coroutine.resume(co) 17 end 18 end 19 table.insert(keys, key) 20 table.insert(vals, val) 21 return coroutine.resume(co) 22 end 23 local co1, co2 = createCo(key1, val1), createCo(key2, val2) 24 local r1, k1, v1 = coroutine.resume(co1) 25 local r2, k2, v2 = coroutine.resume(co2) 26 27 while v1 and v2 do 28 if v1 > v2 then 29 r2, k2, v2 = insertResultAndResume(k2, v2, co2) 30 else 31 r1, k1, v1 = insertResultAndResume(k1, v1, co1) 32 end 33 end 34 while v1 do 35 r1, k1, v1 = insertResultAndResume(k1, v1, co1) 36 end 37 while v2 do 38 r2, k2, v2 = insertResultAndResume(k2, v2, co2) 39 end 40 41 print("-------result--------") 42 for i, v in pairs(keys) do 43 print(v, "= ", vals[i]) 44 end
-- 打印结果为:
-------result-------- a1 = 1 b1 = 2 a2 = 3 b2 = 7 a3 = 9