LUA реализует структуру данных: двусторонняя очередь

предисловие

Встроенная структура данных 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)

Guess you like

Origin blog.csdn.net/sayWhat_sayHello/article/details/115400461