前言
之前发过一篇博文是关于双端队列的。这次的定长队列就基于上次的结构进行改造。
LUA实现数据结构:双端队列
这种数据结构在游戏可见各种记录。例如抽奖记录会不断的更替,后面产生的记录会替代先前的记录。
客户端展示的时候可能需要展示10条,但是你这边存应该存20条之类的。
代码
定长队列实际上是个FIFO的队列,一端进一端出,同时队列的大小固定:
在原本的基础上我们增加了length表示队列当前的长度,一个max_length表示队列的最大长度。
当入队时判断是否大于max_length,大于的话就把先进的元素poll出去。
最后提供了一个获取后入的N个元素的方法。
新建文件名:fixed_length_queue.lua
local List = {
}
List.__index = List
function List:new(max_length)
assert(max_length)
local self = {
first = 0, last = -1, length = 0, max_length = max_length}
return setmetatable(self, List)
end
function List:push(value)
local last = self.last + 1
self.length = self.length + 1
self.last = last
self[last] = value
if self.length > self.max_length then
self:poll()
end
end
function List:poll()
local first = self.first
if first > self.last then error("list is empty") end
local value = self[first]
self[first] = nil -- to allow garbage collection
if first == self.last then
self.first = 0
self.last = -1
else
self.first = first + 1
end
self.length = self.length - 1
return value
end
-- should not change the self in func
-- func return break or not
function List:foreach(func, right_first)
if right_first then
for i = self.last, self.first, -1 do
if func(self[i]) then break end
end
else
for i = self.first, self.last do
if func(self[i]) then break end
end
end
end
function List:clear()
if not self:empty() then
for i = self.first, self.last do
self[i] = nil
end
end
self.first = 0
self.last = -1
end
function List:to_table()
local res = {
}
for i = self.first, self.last do
table.insert(res, self[i])
end
return res
end
function List:get_last_n_rcd(n)
local res = {
}
for i = 0, n - 1 do
if self.first > self.last - i then return res end
table.insert(res, self[self.last - i])
end
return res
end
return List
测试代码
测试代码如下:
local List = require("fixed_length_queue")
local list = List:new(10)
for i = 1, 20 do
list:push(i)
end
list:foreach(print)
print("-----------------")
local ret = list:get_last_n_rcd(5)
for _, v in ipairs(ret) do
print(v)
end
结果:
11
12
13
14
15
16
17
18
19
20
-----------------
20
19
18
17
16