├── tuple.lua ├── stack.lua ├── queue.lua ├── vector.lua ├── README.md └── list.lua /tuple.lua: -------------------------------------------------------------------------------- 1 | --- 2 | --- Generated by EmmyLua(https://github.com/EmmyLua) 3 | --- Created by Dee. 4 | --- DateTime: 2019/3/7 14:00 5 | --- 元組,對修改關閉 6 | --- 7 | 8 | tuple = tuple or {} 9 | 10 | function tuple.create(i_data) 11 | assert(type(i_data) == "table", ">> Dee: shoudle create with table") 12 | 13 | local data = {} 14 | for k,v in pairs(i_data) do 15 | data[#data+1] = v 16 | end 17 | 18 | local t = {} 19 | 20 | local __tostring = function() 21 | return table.concat(data, ",") 22 | end 23 | 24 | local __index = function(i_t, key) 25 | return data[key] 26 | end 27 | 28 | local __newindex = function(i_t, key, v) 29 | error(">> Dee: Limited access") 30 | end 31 | 32 | local __pairs = function() 33 | error(">> Dee: Limited access") 34 | end 35 | 36 | local __ipairs = function(i_t) 37 | local idx = 0 38 | local function iter(i_t) 39 | idx = idx + 1 40 | if idx <= #data then 41 | return idx, data[idx] 42 | end 43 | end 44 | 45 | return iter 46 | end 47 | 48 | local __len = function(v) 49 | return #data 50 | end 51 | 52 | local mt = {__tostring = __tostring, __index = __index, __newindex = __newindex, __pairs =__pairs, __ipairs = __ipairs, __len = __len} 53 | 54 | setmetatable(t, mt) 55 | 56 | return t 57 | end 58 | 59 | 60 | return tuple -------------------------------------------------------------------------------- /stack.lua: -------------------------------------------------------------------------------- 1 | --堆栈实现 2 | stack = stack or {} 3 | 4 | function stack.create() 5 | local data = {} 6 | 7 | local function push(v) 8 | assert(v) 9 | table.insert(data, v) 10 | end 11 | 12 | local function pop() 13 | assert(#data > 0) 14 | table.remove(data) 15 | end 16 | 17 | local function peek() 18 | return #data > 0 and data[#data] or nil 19 | end 20 | 21 | local function clear() 22 | for i=1,#data do 23 | data[i] = nil 24 | end 25 | end 26 | 27 | 28 | 29 | local __tostring = function() 30 | local tmp = {} 31 | for i,v in ipairs(data) do 32 | tmp[#data+1 - i] = v 33 | end 34 | return table.concat(tmp, ",") 35 | end 36 | 37 | local __index = function(i_t, key) 38 | error(">> Dee: Limited access") 39 | end 40 | 41 | local __len = function() 42 | return #data 43 | end 44 | 45 | local __newindex = function(i_t, key, v) 46 | error(">> Dee: Limited access") 47 | end 48 | 49 | local __ipairs = function() 50 | error(">> Dee: Limited access") 51 | end 52 | 53 | local mt = {__tostring = __tostring, __index = __index, __newindex = __newindex, __ipairs = __ipairs, __pairs = __ipairs, __len = __len} 54 | 55 | local t = { 56 | push = push, 57 | pop = pop, 58 | peek = peek, 59 | clear = clear 60 | } 61 | 62 | setmetatable(t, mt) 63 | 64 | return t 65 | end 66 | 67 | return stack -------------------------------------------------------------------------------- /queue.lua: -------------------------------------------------------------------------------- 1 | --- 2 | --- Generated by EmmyLua(https://github.com/EmmyLua) 3 | --- Created by Dee. 4 | --- DateTime: 2019/3/7 11:27 5 | --- FIFO 6 | --- 7 | 8 | queue = queue or {} 9 | 10 | ---@return Queue 11 | function queue.create() 12 | ---数据容器 13 | local data = {} 14 | ---数据长度 15 | local lenght = 0 16 | ---队首索引 17 | local first = 1 18 | 19 | ---获取队首值 20 | local peek = function() 21 | return data[first] 22 | end 23 | 24 | ---压入数据 25 | local enqueue = function(v) 26 | assert(v ~= nil, "nil value") 27 | first = lenght == 0 and 1 or first 28 | lenght = lenght + 1 29 | table.insert(data, first+lenght-1, v) 30 | end 31 | 32 | ---弹出数据 33 | local dequeue = function() 34 | assert(lenght > 0, "nill queue") 35 | 36 | local ret = peek() 37 | data[first] = nil 38 | first = first+1 39 | lenght = lenght - 1 40 | first = lenght == 0 and 1 or first 41 | 42 | if math.fmod(first, 4) == 0 then 43 | local tmp = {} 44 | table.move(data, first, first + lenght, 1, tmp) 45 | 46 | first = 1 47 | data = nil 48 | data = tmp 49 | end 50 | 51 | return ret 52 | end 53 | 54 | local clear = function() 55 | data = {} 56 | first = 1 57 | lenght = 0 58 | end 59 | 60 | local __tostring = function() 61 | local tmp = {} 62 | for i=1,lenght do 63 | tmp[i] = data[i + first - 1] 64 | end 65 | return table.concat(tmp, ",") 66 | end 67 | 68 | local __len = function() 69 | return lenght 70 | end 71 | 72 | local __index = function(i_t, key) 73 | error(">> Dee: Limited access") 74 | end 75 | 76 | local __newindex = function(i_t, key, v) 77 | error(">> Dee: Limited access") 78 | end 79 | 80 | local __ipairs = function(i_t) 81 | local idx = 0 82 | local function iter(i_t) 83 | idx = idx + 1 84 | if idx <= lenght then 85 | return idx, data[first + idx - 1] 86 | end 87 | end 88 | 89 | return iter 90 | end 91 | 92 | local __pairs = function(i_t) 93 | error(">> Dee: Limited access") 94 | end 95 | 96 | local mt = {__tostring = __tostring, __index = __index, __newindex = __newindex, __ipairs = __ipairs, __pairs = __pairs, __len = __len} 97 | 98 | ---@class Queue 99 | local t = { 100 | enqueue = enqueue, 101 | dequeue = dequeue, 102 | peek = peek, 103 | clear = clear 104 | } 105 | 106 | setmetatable(t, mt) 107 | 108 | return t 109 | end 110 | 111 | return queue 112 | -------------------------------------------------------------------------------- /vector.lua: -------------------------------------------------------------------------------- 1 | --- 2 | --- Generated by EmmyLua(https://github.com/EmmyLua) 3 | --- Created by Dee. 4 | --- DateTime: 2019/3/7 14:00 5 | --- 快速遍历修改,低效的增删 6 | --- 7 | 8 | vector = vector or {} 9 | 10 | function vector.create() 11 | local t = {} 12 | 13 | 14 | ---尾添加元素(高效) 15 | function t:add(v) 16 | rawset(self, #self + 1, v) 17 | end 18 | 19 | ---插入(低效) 20 | ---@param k 位置 21 | ---@param v 值 22 | function t:insert(k, v) 23 | assert(k > 0 and k <= #self, "outrange of vector") 24 | 25 | local cnt = #self 26 | for i = cnt, k, -1 do 27 | rawset(self, i+1, self[i]) 28 | end 29 | 30 | rawset(self, k, v) 31 | end 32 | 33 | ---值的索引 34 | ---@return -1不存在 35 | function t:indexOf(i_v) 36 | assert(type(self) == 'table') 37 | 38 | local ret = -1 39 | local cnt = #self 40 | for i = 1, #self do 41 | if self[i] == i_v then 42 | ret = i 43 | end 44 | end 45 | 46 | return ret 47 | end 48 | 49 | ---是否存在某元素 50 | function t:contains(v) 51 | assert(type(self) == 'table') 52 | return self:indexOf(v) ~= -1 53 | end 54 | 55 | ---根据下标索引移除元素(低效) 56 | function t:removeAt(idx) 57 | assert(idx <= #self) 58 | table.remove(self, idx) 59 | end 60 | 61 | ---删除值(非贪婪) 62 | ---@return 删除位置 -1未删除 63 | function t:remove(v) 64 | local ret = self:indexOf(v) 65 | if ret ~= -1 then 66 | self:removeAt(ret) 67 | end 68 | 69 | return ret 70 | end 71 | 72 | ---删除所有值 73 | function t:removeAll(v) 74 | assert(type(self) == 'table') 75 | error(">>Dee: wait ...") 76 | end 77 | 78 | ---排序 79 | function t:sort(comparer) 80 | assert(type(self) == 'table') 81 | table.sort(self, comparer) 82 | end 83 | 84 | ---匹配 85 | ---@param 匹配函数 86 | ---@return idx,value 87 | function t:find(matcher) 88 | assert(type(self) == 'table') 89 | 90 | local _idx, _value = -1, nil 91 | local cnt = #self 92 | for i = 1, cnt do 93 | if matcher(i, self[i]) then 94 | _value = self[i] 95 | _idx = i 96 | break 97 | end 98 | end 99 | 100 | return _idx, _value 101 | end 102 | 103 | --------------------------------metatable--------------------------------------- 104 | t.__newindex = function(i_t,k,v) 105 | error(">> Dee: [], replace with add()") 106 | end 107 | 108 | t.__tostring = function(i_t) 109 | return table.concat(i_t, ',') 110 | end 111 | 112 | t.__pairs = function(...) 113 | error(">> Dee: Limited access") 114 | end 115 | 116 | setmetatable(t, t) 117 | ----------------------------------------------------------------------- 118 | 119 | return t 120 | end 121 | 122 | return vector -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lua-ADT(5.1分支和5.2分支) 2 | 封装的lua数据结构, 元组(tuple)、动态数组(vector)、双向链表(list)、队列(queue)、栈(stack)。 3 | 纯lua方法封装,没有使用oop,延续lua的简洁的风格。封装的数据结构能安全使用,在语言层面过滤掉非法操作,使其使用更加简单高效。 4 | 5 | 所有的类型都支持#获取长度. 6 | > eg. 7 | ```lua 8 | local tuple = require("tuple") 9 | local v = tuple.create({2,3,6}) 10 | print(#v) 11 | ---3 12 | ``` 13 | 14 | ### 元组(tuple) 15 | 需要用table的动态数组初始化(不支持hashtable),只对外公开遍历,修改关闭。 16 | 17 | 遍历: 18 | ```lua 19 | local tuple = require("tuple") 20 | local v = tuple.create({2,3,6}) 21 | 22 | for i,v in ipairs(v) do --只支持ipairs遍历,抛弃了pairs(因为原则上我们是数组,不存在key) 23 | print(i,v) 24 | end 25 | ---1 2 26 | ---2 3 27 | ---3 6 28 | 29 | print(v) --重写了__tostring,方便快速浏览数据 30 | ---2,3,6 31 | 32 | v[2] = 9 --因为对修改关闭了所以这地方修改会抛出错误 33 | ---lua: .\tuple.lua:33: >> Dee: Limited access 34 | ---stack traceback: 35 | ---[C]: in function 'error' 36 | ``` 37 | 38 | ### 动态数组(vector) 39 | 实现高效的遍历和修改,但是新增和删除都不是线性时间复杂度。基本上就是lua table的数组,但是lua的table我们会一不小心就搞成不连续的。比如: 40 | ```lua 41 | local t = {2,4} 42 | t[4] = 9 43 | 44 | print(#t) -- 2 45 | ``` 46 | #### 方法: 47 | * add --尾添加(高效的操作) 48 | * insert --插入(会有内存整理) 49 | * addRange --尾添加一个表, 50 | * removeAt 51 | * remove 52 | * contains 53 | * indexOf 54 | * sort 55 | * find 56 | 57 | #### eg. 58 | ```lua 59 | local vector = require("vector") 60 | local v = vector.create() 61 | 62 | v:add(4) 63 | v:add(5) 64 | v:add(6) 65 | v:add(7) 66 | 67 | for i,v in ipairs(v) do 68 | print(i,v) 69 | end 70 | ---1 4 71 | ---2 5 72 | ---3 6 73 | ---4 7 74 | 75 | print(v) 76 | ---4,5,6,7 77 | 78 | v[4] = 9 --修改值 79 | 80 | print(v) 81 | ---4,5,6,9 82 | 83 | v[7] = 9 84 | ---lua: .\vector.lua:101: outrange of vector 85 | ---stack traceback: 86 | --- [C]: in function 'assert' 87 | ``` 88 | 89 | ### 双向链表(list) 90 | 弥补动态数组增删的不足,提供增删效率,但是遍历和修改效率比较低 91 | 92 | #### 方法: 93 | * addFirst --头添加 94 | * addLast --尾添加 95 | * addBefore --node前添加 96 | * addAfter --node后添加 97 | * removeNode --删除node 98 | * remove --根据值移除 99 | * find --查找node 100 | #### eg. 101 | ```lua 102 | local vector = require("list") 103 | local v = list.create() 104 | 105 | v.addFirst(1) 106 | v.addLast(2) 107 | print(v) 108 | ---1,2 109 | 110 | local node = v.find(1) 111 | node.value = 9 112 | print(v) 113 | ---9,2 114 | 115 | v.removeNode(node) 116 | print(v) 117 | ---2 118 | 119 | v.addLast(10) 120 | v.addLast(20) 121 | v.addLast(30) 122 | print(v) 123 | ---2,10,20,30 124 | 125 | for _,i,v in ipairs(v) do --第一个参数是node, i: index, v: value 126 | print(i,v) 127 | end 128 | ---1 2 129 | ---2 10 130 | ---3 20 131 | ---4 30 132 | ``` 133 | ### 栈(stack) 134 | FILO先进后出, 对修改关闭,关闭遍历,只能通过方法修改数据 135 | #### 方法: 136 | * push --添加 137 | * pop --移除 138 | * peek --返回栈顶数据 139 | * clear --清空 140 | #### eg. 141 | ```lua 142 | local stack = require("stack") 143 | local v = stack.create() 144 | 145 | v.push(1) 146 | v.push(2) 147 | v.push(5) 148 | 149 | print(v) 150 | ---5,2,1 151 | print(v.len) 152 | ---3 153 | v.pop() 154 | print(v) 155 | ---2,1 156 | v.clear() 157 | print(v.len) 158 | ---0 159 | ``` 160 | ### 队列(queue) 161 | FIFO,先进先出,因为是队首删除所以不能使用table.remove 162 | #### 方法: 163 | * enqueue --添加 164 | * dequeue --移除 165 | * peek --返回栈顶数据 166 | * clear --清空 167 | * #queue --获取长度 168 | #### eg. 169 | ```lua 170 | local queue = require("queue") 171 | -- lua table 172 | local cnt = 10000 * 1 173 | 174 | local t = {} 175 | for i=1,cnt do 176 | t[i] = i 177 | end 178 | 179 | local time = os.clock() 180 | while #t > 0 do 181 | -- table.remove(t) 182 | table.remove(t, 1) 183 | end 184 | print(os.clock() - time) 185 | ---1.037s 186 | 187 | local v = queue.create() 188 | 189 | for i=1,cnt do 190 | v.enqueue(i) 191 | end 192 | 193 | 194 | local time1 = os.clock() 195 | while v.len > 10 do 196 | v.dequeue() 197 | end 198 | print(os.clock() - time1) 199 | ---0.005s 200 | ``` 201 | 1w条数据,lua table直接删除表头的耗时1.037s,queue耗时0.005s,而且queue整理内存的步长可以调整,耗时可以进步一提高. 202 | 203 | -------------------------------------------------------------------------------- /list.lua: -------------------------------------------------------------------------------- 1 | --- 2 | --- Generated by EmmyLua(https://github.com/EmmyLua) 3 | --- Created by Dee. 4 | --- DateTime: 2019/3/7 14:00 5 | --- 高效增删有序表,低效遍历 6 | --- 7 | 8 | --[[ 9 | 遍历: 10 | for _,idx, value in ipairs(l) do .. end 11 | for _, value in pairs(l) do ... end 12 | ]] 13 | 14 | list = list or {} 15 | 16 | function list.create() 17 | local lenght = 0 18 | -- 类似stl的方式,头尾只是作为指针使用 19 | local first = {front = nil, next = nil, value = nil} 20 | local last = {front = nil, next = nil, value = nil} 21 | first.next = last 22 | last.front = first 23 | 24 | 25 | ---查找值 26 | ---@param value 27 | ---@return node 28 | local find = function(value) 29 | local ret = nil 30 | local nextNode = first 31 | while nextNode do 32 | nextNode = nextNode.next 33 | if nextNode.value == value then 34 | ret = nextNode 35 | break 36 | end 37 | end 38 | 39 | return ret 40 | end 41 | 42 | ---查找(根据下标查找) 43 | ---@param idx 下标 44 | ---@return node 45 | local findByIdx = function(idx) 46 | local i = 0 47 | local ret 48 | local nextNode = first 49 | while nextNode and i < lenght do 50 | i = i+1 51 | nextNode = nextNode.next 52 | if i == idx then 53 | ret = nextNode 54 | break 55 | end 56 | end 57 | 58 | return ret 59 | end 60 | 61 | ---在node前添加 62 | ---@param node 63 | ---@param v 64 | local addBefore = function(node, v) 65 | assert(node) 66 | 67 | local frontNode = node.front 68 | local newNode = {} 69 | newNode.front = frontNode 70 | newNode.next = node 71 | newNode.value = v 72 | node.front = newNode 73 | frontNode.next = newNode 74 | 75 | lenght = lenght+1 76 | end 77 | 78 | ---在node后添加 79 | ---@param node 80 | ---@param v 81 | local addAfter = function(node, v) 82 | assert(node) 83 | local nextNode = node.next 84 | local newNode = {} 85 | newNode.front = node 86 | newNode.next = nextNode 87 | newNode.value = v 88 | node.next = newNode 89 | nextNode.front = newNode 90 | 91 | lenght = lenght+1 92 | end 93 | 94 | ---在队首添加 95 | ---@param v 96 | local addFirst = function(v) 97 | addAfter(first, v) 98 | end 99 | 100 | ---在队尾添加 101 | ---@param v 102 | local addLast = function(v) 103 | addBefore(last, v) 104 | end 105 | 106 | ---删除节点 107 | ---@param node 108 | local removeNode = function(node) 109 | assert(node) 110 | 111 | local frontNode = node.front 112 | local nextNode = node.next 113 | 114 | if frontNode == nil then 115 | first = nextNode 116 | else 117 | frontNode.next = nextNode 118 | end 119 | 120 | if nextNode ~= nil then 121 | nextNode.front = frontNode 122 | end 123 | lenght = lenght - 1 124 | end 125 | 126 | ---删除节点 127 | ---@param v 128 | local remove = function(v) 129 | local node = find(v) 130 | if node then 131 | removeNode(node) 132 | end 133 | end 134 | 135 | local t = { 136 | addFirst = addFirst, 137 | addLast = addLast, 138 | addBefore = addBefore, 139 | addAfter = addAfter, 140 | removeNode = removeNode, 141 | remove = remove, 142 | find = find, 143 | findByIdx = findByIdx 144 | } 145 | 146 | local mt = { 147 | __index = function(i_t, key) 148 | return findByIdx(key) 149 | end, 150 | __newindex = function(i_t,k,v) 151 | local node = findByIdx(k) 152 | if not node then 153 | error("out range: "..k) 154 | else 155 | node.value = v 156 | end 157 | end, 158 | __tostring = function() 159 | local ret = {} 160 | local next = first.next 161 | while next and next ~= last do 162 | ret[#ret+1] = next.value 163 | next = next.next 164 | end 165 | 166 | return table.concat(ret, ',') 167 | end, 168 | __len = function(v) 169 | return lenght 170 | end, 171 | --迭代器返回node-value 172 | __ipairs = function(i_t) 173 | local idx = 0 174 | local function iter(i_t, node) 175 | idx = idx + 1 176 | if node and node.next ~= last then 177 | return node.next, idx, node.next.value 178 | end 179 | end 180 | 181 | return iter, t, first 182 | end, 183 | __pairs = function(i_t) 184 | local function iter(i_t, node) 185 | if node and node.next ~= last then 186 | return node.next, node.next.value 187 | end 188 | end 189 | 190 | return iter, t, first 191 | end 192 | } 193 | 194 | setmetatable(t, mt) 195 | 196 | return t 197 | end 198 | 199 | return list --------------------------------------------------------------------------------