LUA实现数据结构:双端队列

前言

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)

猜你喜欢

转载自blog.csdn.net/sayWhat_sayHello/article/details/115400461