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

第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章 … 请看该系列的下一篇




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值