长沙有哪些做网站的,怎么做短链接网站,推荐一下网站谢谢,天津网站建设定做一、Lua 中的数据结构
Lua 中并没有像 java、kotlin 语言有专门的数组、列表、集合等数据结构的类#xff0c;而只提供 table 类型#xff0c;但他很强大而且也很灵活#xff0c;而且也在很多场景中天然的就解决了如何对接和使用的问题#xff08;例如模块的引入#xff…一、Lua 中的数据结构
Lua 中并没有像 java、kotlin 语言有专门的数组、列表、集合等数据结构的类而只提供 table 类型但他很强大而且也很灵活而且也在很多场景中天然的就解决了如何对接和使用的问题例如模块的引入这在后面的文章会进行分享
话说回来Lua 没有提供专门的类进行支持所以我们接下来就分享如何用 table 来表示各种数据结构。
二、数组
Lua 中只要使用整数来作为 table 的索引就可以达到数组的效果。但有些不同的是因为 table 的长度是不固定的所以 Lua 数组的长度并不像 java、kotlin 那样是固定长度的。
2-1、初始化一个数组
我们可以使用循环创建一个数组在被初始化的值被获取时则是有值的未被初始化则为 nil。
local array {}
for i 1, 100 doarray[i] 0
endprint(#array, #array) -- #array 100
print(array[9], array[9]) -- array[9] 0
print(array[101], array[101]) -- array[101] nil2-2、修改初始化起始下标
可以进行修改起始下标只是这个会有一个问题长度的计算会不准确因为 Lua 的索引一般都是从 1 开始从下面的例子体会一下
local array {}
for i -5, 5 doarray[i] 0
end-- 这里的长度为 5 是因为从 1 开始计算
print(#array, #array) -- #array 5
print(array[-2], array[-2]) -- array[-2] 0
print(array[5], array[5]) -- array[5] 02-3、创建且初始化数组
还有一种简单的创建方式在创建时初始化数组 这是 table 的一种创建方式可以查看之前分享的文章《Lua 数据类型——表》 local array { 1, 3, 5, 7, 9 }
print(#array, #array) -- #array 5
print(array[3], array[3]) -- array[3] 5
print(array[12], array[12]) -- array[12] nil三、矩阵
3-1、矩阵存储
Lua 的矩阵并没有规定存在的形式是怎样的所以我们可以通过两种方式来存储。
3-1-1、多维数组
多维数组在 java、kotlin 中最为常见就是一个表中的所有元素又是一个表如此循环达到多维效果。
因为比较常规我们就直接上代码看看 Lua 是如何用二维表现矩阵
local M 5
local N 5
local matrix {}
-- 初始化数组
for i 1, M dolocal row {}matrix[i] rowfor j 1, N dorow[j] j iend
end-- 打印数组
for i 1, #matrix dolocal row matrix[i]local rowContent for j 1, #row dorowContent rowContent .. .. row[j]endprint(rowContent)
end-- 2 3 4 5 6
-- 3 4 5 6 7
-- 4 5 6 7 8
-- 5 6 7 8 9
-- 6 7 8 9 103-1-2、一维数组
用一维数组表示多维数组矩阵的话是二维实质上只要控制要每一行的跨度即每一行的元素个数自己管理好元素的下标保证元素间不相互覆盖而且能在需要的时候取出元素。
local matrix {}
local M 5
local N 5
for i 1, N dolocal aux (i - 1) * Mfor j 1, M domatrix[aux j] j iend
endlocal content
for i, v in ipairs(matrix) docontent content .. .. vif i % 5 0 thencontent content .. \nend
end
print(content)-- 2 3 4 5 6
-- 3 4 5 6 7
-- 4 5 6 7 8
-- 5 6 7 8 9
-- 6 7 8 9 103-2、矩阵相乘
3-2-1、常规矩阵相乘
对于矩阵相乘我们最先想到的肯定是 “行乘列”正如如下代码
local a {{ 1, nil },{ nil, 4 },{ 3, 5 }
}
local b {{ 1, 3, nil, 5 },{ 2, nil, 6, 4 }
}
local M 3
local N 4
local K 2
local c {}
-- 初始化 c 矩阵
for i 1, M dolocal row {}c[i] rowfor j 1, N dorow[j] 0end
end
-- 遍历每一个元素行乘列的形式处理
-- c a x b
for i 1, M dofor j 1, N dofor k 1, K doc[i][j] c[i][j] (a[i][k] or 0) * (b[k][j] or 0)endend
end
-- 打印每个元素
for i 1, #c dolocal row c[i]local rowContent for j 1, #row dorowContent rowContent .. .. row[j]endprint(rowContent)
end-- 1 3 0 5
-- 8 0 24 16
-- 13 9 30 353-2-3、稀疏矩阵相乘
这种处理方式对于常规的矩阵没有问题但是对于稀疏矩阵就会有不必要的性能开销和空间的浪费。
所以我们可以换一种思路在之前的文章中有使用过 pairs 进行遍历 table 该函数的特点是保证遍历 table 中的所有元素但不保证先后顺序。
那问题又来了我们在上面的遍历中行乘列的话B 矩阵遍历的是列而不是行所以可以调整一下刚才的循环方式把内循环顺序换一下即可达到行乘行 可以借助上面这张图理解
上一小节的处理方式取 A 矩阵和 B 矩阵各自的蓝色小点和粉色小点相乘然后相加循环直至的处所有结果本小节的处理方式取 A 矩阵的蓝色小点和 B 矩阵的蓝色小点相乘结果存入 C 中的对应位置然后在取 A 矩阵的粉色小点和 B 矩阵的粉色小点相乘结果和 C 的结果相加从而达到行乘行
local a {{ 1, nil },{ nil, 4 },{ 3, 5 }
}
local b {{ 1, 3, nil, 5 },{ 2, nil, 6, 4 }
}
local M 3
local N 4
local K 2
local c {}
-- 初始化 c 矩阵
for i 1, M dolocal row {}c[i] rowfor j 1, N dorow[j] 0end
end
-- 遍历每一个元素行乘列的形式处理
-- c a x b
for i 1, M dofor k 1, K dofor j 1, N doc[i][j] c[i][j] (a[i][k] or 0) * (b[k][j] or 0)endend
end
-- 打印每个元素
for i 1, #c dolocal row c[i]local rowContent for j 1, #row dorowContent rowContent .. .. row[j]endprint(rowContent)
end-- 1 3 0 5
-- 8 0 24 16
-- 13 9 30 35聪明的你肯定会发现现在的操作 paris 还没用上所以接下来就要进行再一次调整得到最终的效果
下面代码需要注意几个小点
使用 pairs 遍历元素避免不必要的遍历最终结果检测是否为 0 如果为 0 则置为 nil 避免不必要的开销
local a {{ 1, nil },{ nil, 4 },{ 3, 5 }
}
local b {{ 1, 3, nil, 5 },{ 2, nil, 6, 4 }
}--- a 和 b 是矩阵
local function mulMatrix(matrixA, matrixB)local c {}-- 遍历 a 所有行for i 1, #matrixA do-- c 矩阵的行结果local resultLine {}-- 遍历 a 矩阵行的每个内容所有的 nil 都会被跳过for k, va in pairs(matrixA[i]) do-- 遍历 b 矩阵行的每个内容所有 nil 都会被跳过for j, vb in pairs(matrixB[k]) dolocal res (resultLine[j] or 0) va * vbresultLine[j] (res ~ 0) and res or nilendendc[i] resultLineendreturn c
end
local c mulMatrix(a, b)-- 打印每个元素
for i 1, #c dolocal row c[i]local rowContent for j 1, #row dorowContent rowContent .. .. (row[j] or nil)endprint(rowContent)
end-- 1 3 nil 5
-- 8 nil 24 16
-- 13 9 30 35四、链表
Lua 中的链表是由一个个的 table 组成每个 table 中有一个字段是指向下一个 table 。 根据上面图我们可以编写出如下构建一个链表
local aPoint {value A, next nil}
local bPoint {value B, next aPoint}
local cPoint {value C, next bPoint}进行遍历也是很方便在 Lua 中 nil 就是 false 所以使用循环遍历一下就可以了
local list cPoint
while list doprint(list.value)list list.next
end-- C
-- B
-- A五、队列
同样队列还是使用 table 来实现因为 Lua 中的 table 并没有长度的约束所以只要控制好单端的出入即普通队列或是双端的出入双端队列即可。
直接上代码我们使用 table 的 insert 和 remove 便能达到双端队列的效果普通队列的话只需要控制在末尾端的出入便可 local queue {}
print(---------------------)
print(前面插入)
table.insert(queue, 1, -10)
table.insert(queue, 1, -5)
table.insert(queue, 1, -1)
---------------------------------------
--- 此时队列内容 -1-5-10
---------------------------------------
print(table.remove(queue, 1)) -- -1
print(table.remove(queue, 1)) -- -5print(---------------------)
print(后面插入)
table.insert(queue, #queue 1, 10)
table.insert(queue, #queue 1, 5)
table.insert(queue, #queue 1, 1)
---------------------------------------
--- 此时队列内容 -101051
---------------------------------------
print(table.remove(queue, #queue)) -- 1
print(table.remove(queue, #queue)) -- 5print(---------------------)
print(输出全部)
---------------------------------------
--- 此时队列内容 -1010
---------------------------------------
for k, v in pairs(queue) doprint(k .. -- .. v)
end
-- 1---10
-- 2--10
但是这里有一个问题我们在 “Lua-表” 的一章分享中提及 table 的 insert 和 remove 如果插入点不在末尾则会导致后面的元素移动在较小数据的情况下这一性能损耗可以忽略但在大量数据的情况下则是一个性能点。
所以我们可以用两个字段来维护队列的头尾这样就不用挪动元素 function listNew()return { first 0, last -1 }
endfunction pushFirst(list, value)local first list.first - 1list.first firstlist[first] value
endfunction pushLast(list, value)local last list.last 1list.last lastlist[last] value
endfunction popFirst(list)local first list.firstif first list.last thenerror(list is empty)endlocal value list[first]list[first] nillist.first first 1return value
endfunction popLast(list)local last list.lastif list.first last thenerror(list is empty)endlocal value list[last]list[last] nillist.last last - 1return value
endprint(---------------------)
print(前面插入)
local queue listNew()
pushFirst(queue, 10)
pushFirst(queue, 5)
pushFirst(queue, 1)
---------------------------------------
--- 此时队列内容 1510
---------------------------------------
print(popFirst(queue)) -- 1print(---------------------)
print(后面插入)
pushLast(queue, 15)
pushLast(queue, 20)
pushLast(queue, 30)
---------------------------------------
--- 此时队列内容 510152030
---------------------------------------
print(popLast(queue)) -- 30print(---------------------)
print(输出全部)
---------------------------------------
--- 此时队列内容 5101520
---------------------------------------
for k, v in pairs(queue) doprint(k .. -- .. v)
end-- -2--5
-- -1--10
-- first---2
-- 1--20
-- 0--15
-- last--1
六、写在最后
Lua 项目地址Github传送门 (如果对你有所帮助或喜欢的话赏个star吧码字不易请多多支持)
如果觉得本篇博文对你有所启发或是解决了困惑点个赞或关注我呀。
公众号搜索 “江澎涌”更多优质文章会第一时间分享与你。