предисловие
Встроенная структура данных Lua обычно одна: таблица. Однако во многих случаях наш бизнес требует различных структур, и эти структуры могут быть написаны на основе таблиц.
метод двойной очереди
Существует несколько методов, предоставляемых двусторонней очередью:
- иди налево
- опущены
- Иди направо
- сразу
Структура предоставлена "программистом на 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)