数组结构

来源:互联网 发布:php手机网页源码 编辑:程序博客网 时间:2024/06/05 14:48

1 数组

使用整数来索引table即可在lua中实现数组。因此数组没有固定大小,可以根据需要增长。通常初始化一个数组大小时,也间接的定义了它的大小。

例如:

a = {}    --新建一个数组for i=1,100 doa[i] = 0endprint(#a) --   100  长度操作符(#)依赖这个事实计算数组的大小

--可以使用0或1 任意值作为索引a = {}for i = -5, 5 doprint(i)   --  -5 -4 -3 -2 -1 1 2 3 4 5 end
lua中一般习惯1作为索引。lua的长度和操作符都遵循这个约定。


2 矩阵和多维数组

lua中两种方式表示矩阵,一种是使用一个‘数组的数组’也就是说,一个table中的每个元素是另一个table。例如可以使用下面代码创建一个nm列的矩阵

mt = {} -- 创建矩阵for i=1,N domt[i] = {}  -- 创建一个行for j=1,M domt[i][j] = 0endend
由于Luatable是对象,所以每一行我们必须显式地创建一个table,比起cpascal,这显得冗余,但另一方面也提供了更多的灵活性,例如可修改前面的例子创建一个三角矩阵:
for j=1,M do
改成:

for j=1,i do

这样实现的三角矩阵比起整个矩阵,仅使用一半的内存空间。

表示矩阵的另一方法,是将行和列组合起来。如果索引下标都是整数,通过第一个索引乘于一个常量(列)再加上第二个索引,看下面的例子实现创建n行m列的矩阵:

mt = {}           -- 创建矩阵for i=1,N do    for j=1,M do       mt[i*M + j] = 0    endend

如果索引是字符串,可用一个单字符将两个字符串索引连接起来构成一个单一的索引下标,例如一个矩阵m,索引下标为s和t,假定s和t都不包含冒号,代码为:m[s..':'..t],如果s或者t包含冒号将导致混淆,比如("a:", "b")和("a", ":b"),当对这种情况有疑问的时候可以使用控制字符来连接两个索引字符串,比如'\0'。

实际应用中常常使用稀疏矩阵,稀疏矩阵指矩阵的大部分元素都为空或者0的矩阵。例如,我们通过图的邻接矩阵来存储图,也就是说:当m,n两个节点有连接时,矩阵的m,n值为对应的x,否则为nil。如果一个图有10000个节点,平均每个节点大约有5条边,为了存储这个图需要一个行列分别为10000的矩阵,总计10000*10000个元素,实际上大约只有50000个元素非空(每行有五列非空,与每个节点有五条边对应)。很多数据结构的书上讨论采用何种方式才能节省空间,但是在Lua中你不需要这些技术,因为用table实现的数据本身天生的就具有稀疏的特性。如果用我们上面说的第一种多维数组来表示,需要10000个table,每个table大约需要五个元素(table);如果用第二种表示方法来表示,只需要一张大约50000个元素的表,不管用那种方式,你只需要存储那些非nil的元素。


链表


Lua中用tables很容易实现链表,每一个节点是一个table,指针是这个表的一个域(field),并且指向另一个节点(table)。例如,要实现一个只有两个域:值和指针的基本链表,代码如下:

根节点:

list = nil

在链表开头插入一个值为v的节点:

list = {next = list, value = v}

要遍历这个链表只需要:

local l = listwhile l do    print(l.value)    l = l.nextend

其他类型的链表,像双向链表和循环链表类似的也是很容易实现的。然后在Lua中在很少情况下才需要这些数据结构,因为通常情况下有更简单的方式来替换链表。比如,我们可以用一个非常大的数组来表示栈,其中一个域n指向栈顶。







0 0
原创粉丝点击