Lua table数据结构 算法分析

一、数据结构
1、Node
next:当hash冲突时,next = 冲突的node位置 - 应该
2、Table
lsizenode:hash数组大小 = 2^lsizenode
node :指向hash部分
arraysize :数组部分大小
array :指向数组部分
lastfree :指向hash表中空闲的节点。每次hash表发生冲突时,都会把节点放在lastfree位置。lastfree 初始为hash尾部,冲突时向前移动到下一个空闲节点。
metable :指向元表
二、算法
1、hash表插入过程
{
key在数组部分:返回node
key在hash部分:
查找是否存在key:
存在 :返回node
不存在:找空闲节点插入新key
找到空闲节点:赋值node key
找不到:rehash重新非配空间,再次尝试插入
}
hash表key的插入位置查找过程:
2、rehash
{
统计数组table整数key和所有节点个数
计算数组部分应当分配的大小( 计算规则 数组部分:空间利用率 > 50% )
计算hash数组大小 ( 不能放入数组部分的,全部放入到hash部分 )
分配空间
}

3、取长度getn
table获取长度算法遇到并不是顺序查找数组部分和hash部分的,而是 二分查找 ,所以存在空洞的nil值时,返回的长度是不稳定的。算法认为nil为结束的标识,所以二分查找到n n满足array[n] != nil && array[n+1] ==nil。
4、查找findindex(key)
{
key ==nil:返回0
key!=nil 查找key所在的位置
找到 :返回位置
找不到:报错
}

5、迭代
luaH_next(key)
{
findindex查找key位置
将value压入栈和 下个key 压入栈
}

6、遍历:
//  进行下面步骤前先将  table  压入栈顶  
  int  nIndex = lua_gettop( pLua );   //   table  索引值  
 lua_pushnil( pLua );   // nil  入栈作为初始  key  在调用 lua_next 时 取出的key是空,findindex会返回 0 也就是第一个key值
  while ( 0 != lua_next( pLua, nIndex ) )  //弹出当前key 压入当前value 和下个key入栈
 { 
     lua_pop( pLua, 1 );   //  弹出  value ,让  key  留在栈顶进行下次迭代  
 } 
  //  现在栈顶是  table
三、总结
(1)table占用三部分空间,table本身结构+数组部分+hash部分。
(2)table在每次resize时保证数组部分的空间利用率大于50%,不能存放数组部分的key全部放到hash数组中,当hash中没有空闲节点时,进行resize(resize时数组部分不一定是满的)重新计算数组和hash数组应该分配的空间大小。
(3)table进行取长度时,算法在连续的整数key情况下是稳定的,在存在空洞nil的情况下不稳定,这时进行取长度操作可能返回一个错误的长度

猜你喜欢

转载自blog.csdn.net/dingqinghui/article/details/78125371