支持对列表操作的栈(lua)

来源:互联网 发布:touchslide.js 编辑:程序博客网 时间:2024/05/29 08:54

很多时候列表都不像我们想象的那么容易使用。
举个例子:

        local t = {}        table.insert(t,{k=1})        table.insert(t,{k=2})        table.insert(t,{k=3})        table.insert(t,{k=4})        table.insert(t,{k=5})        table.insert(t,{k=6})        table.insert(t,{k=7})        table.insert(t,{k=8})        for i=1,table.getn(t) do            print(t[i].k)            if t[i].k == 8 then                table.insert(t,{k=9})            end        end        print("===========================")        for i=1,table.getn(t) do            print(t[i].k)        end

看上面的例子,在遍历列表结束时我又插入了一个值,按理说现在表已经长度为9了,表应该接着遍历才对,可是表遍历到此就结束了。  
看输出:
[LUA-print] 1
[LUA-print] 2
[LUA-print] 3
[LUA-print] 4
[LUA-print] 5
[LUA-print] 6
[LUA-print] 7
[LUA-print] 8
[LUA-print] ===========================
[LUA-print] 1
[LUA-print] 2
[LUA-print] 3
[LUA-print] 4
[LUA-print] 5
[LUA-print] 6
[LUA-print] 7
[LUA-print] 8
[LUA-print] 9
表没有继续遍历,由后面的输出可见,表确实变长了。类似的表操作还有很多,默认的表构造都不能满足我的要求。所以我写了个新的队列。看代码:

        local stack = util.TableStack.new()        stack:pushElement({k = 1})        stack:pushElement({k = 2})        stack:pushElement({k = 3})        local v1 = {k = 4}        stack:pushElement(v1)        stack:pushElement({k = 5})        stack:pushElement({k = 6})        stack:pushElement({k = 7})        stack:pushElement({k = 8})        stack:pushElement({k = 9})        stack:pushElement({k = 10})        stack:pushElement({k = 11})        function trace(v_k)            print(" k= "..v_k.k)            if v_k.k == 11 then                stack:pushElement({ k = 12})                stack:delElement(v_k)            end        end        stack:checkElement(trace)        print("trace2________________")        function trace2(v_k)            print(v_k.k)        end        stack:checkElement(trace2)

看输出:

[LUA-print] k= 1
[LUA-print] k= 2
[LUA-print] k= 3
[LUA-print] k= 4
[LUA-print] k= 5
[LUA-print] k= 6
[LUA-print] k= 7
[LUA-print] k= 8
[LUA-print] k= 9
[LUA-print] k= 10
[LUA-print] k= 11
[LUA-print] k= 12
[LUA-print] trace2________________
[LUA-print] 1
[LUA-print] 2
[LUA-print] 3
[LUA-print] 4
[LUA-print] 5
[LUA-print] 6
[LUA-print] 7
[LUA-print] 8
[LUA-print] 9
[LUA-print] 10
[LUA-print] 12

新的对象支持对表的任意操作,下面贴源代码:

 ---- Author: xiaowa-- Date: 2015-10-04 08:33:36---- 高效的table stack local HashMap = import(".HashMap")local TableStack = TableStack or class("TableStack")function TableStack:ctor()    self.stack_ = nil    self.stack_end_ = nil --栈末尾的元素    self.stack_num_ = 0 --栈元素数量    self.hash_ = HashMap.new()  --高效访问    self.PTR_NEXT = nil --保存下一个元素的指针    self.CHECK = false --是否正在遍历表end--[[    @function 压入栈顶一个元素    @return Element#被压入的元素--]]function TableStack:pushElement(value)    assert(type(value) == "table", string.format("%s:pushElement() - invalid value", self.class.__cname))    self.stack_num_ = self.stack_num_ + 1    local ptr = self.stack_    if ptr then        self.stack_end_.next = {}        self.stack_end_.next.value = value        self.stack_end_.next.prev = self.stack_end_ --双向表,这样pop就快        self.stack_end_ = self.stack_end_.next    else --栈没有初始化        self.stack_ = {}        self.stack_.value = value        self.stack_end_ = self.stack_    end    self.hash_:setElement(value,self.stack_end_)    --反向引用,利于查找    --调整遍历指针代码    if self.CHECK then        if self.PTR_NEXT == nil then            self.PTR_NEXT = self.stack_end_        end    end    return valueend--[[    @function在栈的开头插入元素    @return Element#被插入的元素--]]function TableStack:insertFirstElement(value)    assert(type(value) == "table", string.format("%s:insertFirstElement() - invalid value", self.class.__cname))    self.stack_num_ = self.stack_num_ + 1    local ptr = self.stack_    if ptr then        self.stack_.prev = {}        self.stack_.prev.value = value        self.stack_.prev.next = self.stack_        self.stack_ = self.stack_.prev    else --栈没有初始化        self.stack_ = {}        self.stack_.value = value        self.stack_end_ = self.stack_    end    self.hash_:setElement(value,self.stack_)    --反向引用,利于查找    return valueend--[[    @function 删除某个元素    @return Element#被删除的元素--]]function TableStack:delElement(value)    assert(value ~= nil, string.format("%s:delElement() - invalid value", self.class.__cname))    local v = self.hash_:getValue(value)    if v == nil then        return    end    --调整遍历指针代码    if self.CHECK then        if self.PTR_NEXT == v then            self.PTR_NEXT = self.PTR_NEXT.next        end    end    self.stack_num_ = self.stack_num_ - 1   --数量减1(检查出的漏掉的代码)    if v.prev and v.next then --不是第一个元素        v.prev.next = v.next        v.next.prev = v.prev        v.prev = nil        v.next = nil        self.hash_:delElement(value)        return v.value    elseif v.prev == nil and v.next then --删除的是第一个元素        self.stack_ = self.stack_.next        self.stack_.prev = nil        v.next = nil        self.hash_:delElement(value)        return v.value    elseif v.prev and v.next == nil then --删除最后一个元素        self.stack_end_ = self.stack_end_.prev        self.stack_end_.next = nil        v.prev = nil        self.hash_:delElement(value)        return v.value    elseif v.prev == nil and v.next == nil then --删除唯一元素        self.stack_ = nil        self.stack_end_ = nil        self.hash_:delElement(value)        return v.value    else        printLog("error","this is No way!") --这不可能    endend--[[    @function 弹出元素    @return Element#value--]]function TableStack:popElement()    if self.stack_end_ == nil then        return nil    end    --调整遍历指针代码    if self.CHECK then        if self.PTR_NEXT == self.stack_end_ then            self.PTR_NEXT = self.PTR_NEXT.next        end    end    self.stack_num_ = self.stack_num_ - 1   --数量减1    local ptr_prev    ptr_prev = self.stack_end_.prev    if ptr_prev then        ptr_prev.next = nil        self.stack_end_.prev = nil        local value = self.stack_end_.value        self.stack_end_ = ptr_prev        self.hash_:delElement(value) --在hash 中删除key        return value    else --self.stack_end_ 是第一个元素,就是只有1个元素了        self.stack_ = nil        local value = self.stack_end_.value        self.stack_end_ = nil        self.hash_:delElement(value) --在hash 中删除key        return value    endend--[[    @function 弹出第一个元素    @return Element#value--]]function TableStack:removeFirstElement()    if self.stack_ == nil then        return nil    end    local ptr,ptr_next = self.stack_,self.stack_.next    if ptr then        --调整遍历指针代码        if self.CHECK then            if self.PTR_NEXT == ptr then                self.PTR_NEXT = self.PTR_NEXT.next            end        end        self.stack_num_ = self.stack_num_ - 1   --数量减1        if ptr_next then            ptr_next.prev = ptr.prev            self.stack_ = ptr_next            self.hash_:delElement(ptr.value) --在hash 中删除key            return ptr.value        else            self.stack_ = nil            self.stack_end_ = nil --修复添加代码            self.hash_:delElement(ptr.value) --在hash 中删除key            return ptr.value        end    end    return nilend--[[    @function 检查效果,检查函数中可以对栈进行操作,删除当前检查对象就会停止检查,删除其他对象仍会继续    @param function#检查函数,返回true 时停止检查    @return nil--]]function TableStack:checkElement(fun)    assert(type(fun) == "function", string.format("%s:checkElement() - invalid value", self.class.__cname))    self.CHECK = true    local ptr = self.stack_    while ptr do        self.PTR_NEXT = ptr.next        if fun(ptr.value) then            break         end        ptr = self.PTR_NEXT    end    self.CHECK = falseend--[[    @function 返回栈的长度    @return number#栈的元素个数--]]function TableStack:Len()    return self.stack_num_endreturn TableStack
0 0
原创粉丝点击