数组队列Queue

# 使用循环队列的方式

local arrayext = require("arrayext")

local Queue = {}
Queue.__cname = "util.Queue"
Queue.__index = Queue

local ClearTypeEnum = {
    Reset = nil,
    FillNil = 1,
    Keep = 2,
}
Queue.ClearTypeEnum = ClearTypeEnum

function Queue.new(capacity)
    local obj = {}
    setmetatable(obj, Queue)
    obj:ctor(capacity)
    return obj
end

function Queue:ctor(capacity)
    self.arr = {}
    self.capacity = capacity or 8
    self.head = 1 ---当前:先加减再操作
    self.tail = 1 ---后一个位置: 先操作再加减
    self.count = 0
end

function Queue:Clear(clearType)
    if self:GetCount() < 1 then return end

    if clearType == ClearTypeEnum.Reset then
        self.arr = {}
    elseif clearType == ClearTypeEnum.FillNil then
        if self.head < self.tail then
            for i=self.head,self.tail-1 do
                self.arr[i] = nil
            end
        else
            for i=self.head,self.capacity do
                self.arr[i] = nil
            end
            for i=1,self.tail-1 do
                self.arr[i] = nil
            end
        end
    end
    self.capacity = 0
    self.head = 1
    self.tail = 1
    self.count = 0
end

function Queue:GetCount()
    return self.count
end

function Queue:_GetMod(index)
    if index > self.capacity then
        index = index - self.capacity
    elseif index < 1 then
        index = index + self.capacity
    end
    return index
end

function Queue:_Expand()
    --注意: 交换次数为奇数次, 还要再多交换一次(把最后2个元素调整下)
    if self.head > 1 then
        local j = 1
        for i=self.head,self.capacity do
            arrayext.Swap(self.arr, j, i)
            j = j + 1
        end
        local swapCount = self.capacity - self.head + 1
        if 1 == math.fmod(swapCount, 2) then
            arrayext.Swap(self.arr, self.capacity, self.capacity - 1)
        end
    end
    self.head = 1
    self.tail = self.count + 1
    self.capacity = self.capacity * 2
end

function Queue:Enqueue(v)
    self.arr[self.tail] = v
    self.tail = self:_GetMod(self.tail + 1)
    self.count = self.count + 1

    if self.head == self.tail then
        self:_Expand()
    end
end

function Queue:Dequeue()
    if self:GetCount() < 1 then return nil end
    local ret = self.arr[self.head]
    self.arr[self.head] = nil

    self.head = self:_GetMod(self.head + 1)
    self.count = self.count - 1
    return ret
end

function Queue:PeekFirst()
    if self:GetCount() < 1 then return nil end
    return self.arr[self.head]
end

function Queue:PeekLast()
    if self:GetCount() < 1 then return nil end
    local index = self:_GetMod(self.tail - 1)
    return self.arr[index]
end

function Queue:__tostring()
    if self:GetCount() < 1 then return "" end

    local strTb = {}
    if self.head < self.tail then
        for i=self.head,self.tail-1 do
            table.insert(strTb, tostring(self.arr[i]))
        end
    else
        for i=self.head,self.capacity do
            table.insert(strTb, tostring(self.arr[i]))
        end
        for i=1,self.tail-1 do
            table.insert(strTb, tostring(self.arr[i]))
        end
    end

    return table.concat(strTb, ",")
end

function Queue:GetIterator()
    if nil == self.iterator then
        self.iterator = function(tb, k)
            return self:Dequeue()
        end
    end
    return self.iterator
end

return Queue

 

posted @ 2021-11-12 00:29  yanghui01  阅读(33)  评论(0编辑  收藏  举报