在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
这个网站是一个老外的博客,有很多关于lua和love2d的内容,可惜被墙了。这几天也不知道 如何继续love2d,便想着干脆捡一些有用的简单翻译一下,或许能产生点灵感。对于lua而言 我感觉最强大的就是它的table了,有点lisp里的表的感觉。 简译如下,原文在此。 作为一个创建自定义数据结构的例子, 我想你得先了解一些关于链表的实现 linkedlists 。 注意这并不是一篇深入的教程,大部分情况下我会展示一些代码片段。 链表是很好的数据结构,可以完美的实现高效的添加,删除,遍历。唯一的缺点是你不能通过 索引查找元素。 有多种链表,最常见的两种是单链表、双链表。各种链表都有一堆节点,并维持着指向节点之间 的索引。单链表有指向头节点的索引,每个节点都指向下一个节点。双链表有指向头节点和尾节 点的索引,每个节点都指向上一个和下一个节点。若想了解更多,参考Wikipedia page 。 我决定实现双链表。它的效率稍逊单链表,但是更好用,因为它允许逆向遍历。让我们先来 一段OOP代码。 list = {} list.__index = list setmetatable(list, { __call = function(_, ...) local t = setmetatable({}, list) for _, v in ipairs{...} do t:push(v) end end }) --译者注:setmetatable设置元表,__call标示table调用时会执行的函数 --这里调用list时就会自动执行__call,__call的内容是先绑定一个空表{},再把参数放入{}。 它允许用户想这样创建链表:
注意所有的元素都必须是tabel,这样元素才支持索引。(译注:如同c语言里的节点是结构体)。 我展示的第一个函数式简单的 function list:push(t) if self.last then --如果有节点 self.last._next = t t._prev = self.last self.last = t else --如果是空链表 self.first = t self.last = t end self.length = self.length + 1 end
function list:pop() if not self.last then return end local ret = self.last if ret._prev then ret._prev._next = nil self.last = ret._prev ret._prev = nil else -- this was the only node self.first = nil self.last = nil end self.length = self.length - 1 return ret end
我们使用的更灵活的添加和删除函数式 function list:insert(t, after) if after then if after._next then after._next._prev = t t._next = after._next else self.last = t end t._prev = after after._next = t self.length = self.length + 1 elseif not self.first then -- this is the first node self.first = t self.last = t end end function list:remove(t) if t._next then if t._prev then t._next._prev = t._prev t._prev._next = t._next else -- this was the first node t._next._prev = nil self._first = t._next end elseif t._prev then -- this was the last node t._prev._next = nil self._last = t._prev else -- this was the only node self._first = nil self._last = nil end t._next = nil t._prev = nil self.length = self.length - 1 end
local function iterate(self, current) if not current then current = self.first elseif current then current = current._next end return current end function list:iterate() return iterate, self, nil end 这仅是顺序迭代,但是实现一个逆向的不难。 到结束的时候了,下面是个使用链表的例子: require("list") local a = { 3 } local b = { 4 } local l = list({ 2 }, a, b, { 5 }) l:pop() l:shift() l:push({ 6 }) l:unshift({ 7 }) l:remove(a) l:insert({ 8 }, b) print("length", l.length) for v in l:iterate() do print(v[1]) end 如果需要全部的代码请git检出 gist #4084042.
--注,下面即是 list.lua list = {} list.__index = list setmetatable(list, { __call = function(_, ...) local t = setmetatable({ length = 0 }, list) for _, v in ipairs{...} do t:push(v) end return t end }) function list:push(t) if self.last then self.last._next = t t._prev = self.last self.last = t else -- this is the first node self.first = t self.last = t end self.length = self.length + 1 end function list:unshift(t) if self.first then self.first._prev = t t._next = self.first self.first = t else self.first = t self.last = t end self.length = self.length + 1 end function list:insert(t, after) if after then if after._next then after._next._prev = t t._next = after._next else self.last = t end t._prev = after after._next = t self.length = self.length + 1 elseif not self.first then -- this is the first node self.first = t self.last = t end end function list:pop() if not self.last then return end local ret = self.last if ret._prev then ret._prev._next = nil self.last = ret._prev ret._prev = nil else -- this was the only node self.first = nil self.last = nil end self.length = self.length - 1 return ret end function list:shift() if not self.first then return end local ret = self.first if ret._next then ret._next._prev = nil self.first = ret._next ret._next = nil else self.first = nil self.last = nil end self.length = self.length - 1 return ret end function list:remove(t) if t._next then if t._prev then t._next._prev = t._prev t._prev._next = t._next else -- this was the first node t._next._prev = nil self._first = t._next end elseif t._prev then -- this was the last node t._prev._next = nil self._last = t._prev else -- this was the only node self._first = nil self._last = nil end t._next = nil t._prev = nil self.length = self.length - 1 end local function iterate(self, current) if not current then current = self.first elseif current then current = current._next end return current end function list:iterate() return iterate, self, nil end |
请发表评论