您的位置:首页 > 编程语言 > Lua

《Lua程序设计[第二版]》第11,12章笔记

2012-10-26 17:25 197 查看
第11章 数据结构

Lua中的table不是一种简单的数据结构,它可以作为其他数据结构的基础。通过table来表示数组、记录、线性表、队列、集合等。

11.1数组

使用整数来索引table即可在Lua中实现数组,一般以1作为数组起始索引。

a = {}

for i=1, 1000 do

a[i] = 0

end

print(#a) –> 1000

11.2 矩阵与多维数组

两种方法表示矩阵。第一种是使用一个“数组的数组”,也就是说,一个table中的每个元素是另一个table。下面的代码创建了N X M的零矩阵:

mt = {}

for i=1, N do

mt[i] = {}

for j=1, M do

mt[i][j] = 0

end

end

第二个方法时将两个索引合并为一个索引。如果两个索引是整数,可以将第一个索引乘以一个适当的常量,并加上第二个索引。以下代码就是用这种方法来创建N X M的零矩阵:

mt = {}

for i = 1, N do

for j = 1, M do

mt[(i-1)*M + j] = 0

end

end

11.3 链表

在Lua中实现链表,每个结点以一个table来表示,一个“链接”只是结点table中的一个字段,该字段包含了对其他table的引用。

list = nil

list = {next = list, value = v}

local l = list

while l do

print(l.value)

l = l.next

end

11.4 队列与双向队列

使用Lua的table库提供的insert和remove操作来实现队列,但这种方式实现的队列处理大数据量时效率太低。一种更高效的实现是使用两个索引,分别用于首尾的两个元素:
function ListNew ()
return {first = 0, last = 1}
end

List = {}
function List.new()
return {first = 0, last = -1}
end

function List.pushfirst (list, value)
local first = list.first - 1
list.first = first
list[first] = value
end

function List.pushlast(list, value)
local last = list.last + 1
list.last = last
list[last] = value
end

function List.popfirst (list)
local first = list.first
if first > list.last then
enderror ("list is empty")
end
local value = list[first]
list[first] = nil  -- 为了允许垃圾收集
list.first = first + 1
return value
end

function List.poplast (list)
local last = list.last
if list.first > last then
error("list is empty")
end
local value = list[last]
list[last] = nil  -- 为了允许垃圾收集
list.last = last - 1
return value
end


11.5 集合与无序组(bag)



11.6 字符串缓冲



11.7 图

Lua允许程序员写出多种图的实现,每种实现都有其所适用的算法。这里要介绍一种简单的面向对象的实现,其中结点表示为对象,边表示为结点间的引用。

每一个结点表示为一个table,这个table有两个字段:name(结点的名称)和adj(于此结点邻接的结点集合)。下面是代码的实现:
-- 根据给定的名称返回对应的结点
local function name2node (graph, name)
if not graph[name] then		 -- 如果结点不存在
graph[name] = {name = name, adj = {}}
end
return graph[name]
end

-- 构造图
function readgraph ()
local graph = {}
for line in io.lines() do 	-- 切分行中的两个名称
local namefrom, nameto = string.match(line, "(%s+)%s+(%s+)")
local from = name2node(graph, nameto)	-- 查找相应的结点
from.adj[to] = true 	-- 将“to“添加到”from“的邻接集合
end
return graph
end

-- 函数findpath采用深度优先遍历算法,在两个结点间搜索一条路径
-- 它的第一个参数是当前结点,第二个参数是目标节点,
-- 第三个参数用于保存从起点到当前结点的路径,第四个参数是已访问结点的集合
-- 【注意】该算法直接对结点进行操作,而不是它们的名称
function findpath (curr, to, path, xisited)
path = path or {}
visited = visited or {}
if visited[curr] then		-- 结点是否已访问过?
return nil 				-- 这里没有路径
end
visited[curr] = true		-- 将结点标记为已访问
path[#path + 1] = curr		-- 将其加到路径中
if curr == to then 			-- 最后的结点吗?
return path
end
for node in pairs(curr.adj) do 		-- 尝试所有的邻接结点
local p = findpath(node, to, path, visited)
if p then
return p
end
end
path[#path] = nil			-- 从路径中删除节点
end

-- 测试上面所列函数
function printpath(path)
for i=1, #path do
print(path[i].name)
end
end

g = readgraph()
a = name2node(g, "a")
b = name2node(g, "b")
p = findpath(a,b)
if p then
printpath (p)
end


第12章 数据文件与持久性

12.1 数据文件



12.2 串行化(Serialization)

通常需要串行化一些数据,也就是将数据转换为一个字节流或一个字符流。然后就可以将其存储到一个文件中,或者通过网络连接发送出去了。

Lua5.1提供了一种安全的方法来括住任意字符串的方法。标记方式为:[=[…]=],用于长字符串。

12.2.1 保存无环的table



12.2.2 保存有环的table



第13章 … 请看该系列的下一篇
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: