前言
lua内置的数据结构总的来说就一个:table。然而很多时候我们的业务需要各种各样的结构,这些结构都能基于table来写。
双端队列的方法
双端队列提供的方法主要有几种:
- 左进
- 左出
- 右进
- 右出
《programmer in lua》提供的结构:
function listNew()
return {
first = 0, last = -1}
end
function pushFirst(list, value)
local first = list.first - 1
list.first = first
list[first] = value
end
function pushLast(list, value)
local last = list.last + 1
list.last = last
list[last] = last
end
function popFirst(list)
local first = list.first
if first > list.last then error("list is empty") end
local value = list[first]
list[first] = nil
list.first = first + 1
return value
end
function popLast(list)
local last = list.last
if list.first > last then errot("list is empty") end
local value = list[last]
list[last] = nil
list.last = last - 1
end
为了方便我们进行测试,我们要实现一个打印内部值的方法:
function foreach(list, func)
for i = list.first, list.last do
if func(list[i]) then
break
end
end
-- 需要注意的是如果是table,用print可能无法很好的了解到内部的内容
function printQ(list)
foreach(list, print)
end
调用方法大致如下:
local list = listNew()
for i = 1, 10 do
pushFirst(list, i)
end
printQ(list)
封装版本
这个版本对上面的版本的封装,新建一个文件名为List.lua
:
local List = {
}
List.__index = List
function List:new()
local self = {
first = 0, last = -1}
return setmetatable(self, List)
end
local function _itor(self, k)
return k <= self.last - self.first and k+1 or nil, self[self.first+k]
end
function List:__pairs()
return _itor, self, 0
end
function List:pushFirst(value)
local first = self.first - 1
self.first = first
self[first] = value
end
function List:pushLast(value)
local last = self.last + 1
self.last = last
self[last] = value
end
function List:popFirst()
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
return value
end
function List:popLast ()
local last = self.last
if self.first > last then error("list is empty") end
local value = self[last]
self[last] = nil -- to allow garbage collection
if last == self.first then
self.first = 0
self.last = -1
else
self.last = last - 1
end
return value
end
function List:empty()
return (self.first > self.last)
end
function List:length()
return (self.first > self.last) and 0 or (self.last-self.first+1)
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:left()
local first = self.first
if first > self.last then error("list is empty") end
return self[first]
end
function List:right()
local last = self.last
if self.first > last then error("list is empty") end
return self[last]
end
function List:to_table()
local res = {
}
for i = self.first, self.last do
table.insert(res, self[i])
end
return res
end
List.__ipairs = List.__pairs
List.len = List.length
List.size = List.length
List.push = List.pushLast
List.pop = List.popFirst
return List
在调用方式上,具体的调用方式如下:
local List = require("List")
local list = List:new()
for i = 1, 10 do
list:push(i)
end
list:foreach(print)