不止八股---Lua原理笔记(2)表(1)

表的构成

typedef union TKey {
  struct {
    TValuefields;
    struct Node *next;  /* for chaining */
  } nk;
  TValue tvk;
} TKey;

typedef struct Node {
  TValue i_val;
  TKey i_key;
} Node;

// lua table的基本数据结构
typedef struct Table {
  //GC有关
  CommonHeader;
  GCObject *gclist;
  
  //哈希部分
  lu_byte lsizenode;  /* log2 of size of `node' array */
  Node *node;     /* hash part */
  Node *lastfree;  /* any free position is before this position */
 
  //数组部分
  TValue *array;  /* array part */
  int sizearray;  /* size of `array' array */
 
  //元表和其他
  struct Table *metatable;
  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */
 
} Table;

数组部分

用于存放连续整数键(从1开始的)的值,这样可以提高访问整数键值的性能

数组内容是 TValue *array; 长度是int sizearray;

哈希部分

用于存放非整数键值和非连续整数见的值,nil不能作为键

哈希表存放在Node* node 数组,数组的大小是2^ lsizenode

lastfree的含义

空闲的node在lastfree的左边,lastfree指向的内存,以及右边的内存均已被使用

发生冲突,lastfree向左找,找到了空闲就停止,然后把元素塞进去

元表和其他部分

表的基本操作

表的创建和初始化

初始化的时候,哈希表lsizenode=0, 按照公式应该其大小为数组为1 。为了维护哈希表数组长度为2^lsizenode这个规则,哈希表Node指向一个共用的dummyNode结点

查询

下标

怎么知道我这个元素在哈希表的哪个下标?

index = hash_value & ((2 ^ lsizenode) - 1)

(2 ^ lsizenode)是哈希表数组大小

& ((2 ^ lsizenode) - 1) 相当于取mod,但是比取mod好

为啥要取mod,就是让哈希值能映射到数组内,不会飞出去

这里的 维护(2 ^ lsizenode) 这个大小的用处在这里体现了

如果 lsizenode是4(即哈希表大小为16),那么(2^lsizenode) - 1 是15,二进制表示为 (1111)。任何数与 (1111) 进行按位与操作,都会得到一个在0到15之间的结果,这正好适合索引一个大小为16的数组。

例如key 为19

其实就是把超出数组长度的二进制部分数据直接给砍了,有点像计网掩码的意思

查找

是int类型

key为k,k如果小于arraySize 就直接返回array[k-1]

否则查找哈希表

        首先index = k & (2^lsizenode-1)  ,以hash[index]为起点查找

        比较,如果不是就找next,next==0就认为找不到了

不是int 类型就直接找哈希表

在前面基础上 k 要自己调用哈希函数算一个哈希值出来key_hash

然后就是上面的步骤,index = key_hash & (2^lsizenode-1),

以hash[index]节点为起点......

插入

整数而且是在数组范围内

key为3 找到,刚好为空插入

超出找哈希表插入

发生哈希冲突,lastfree向左找然后插入,然后设置一下next

再次冲突,但是13 拿 7原本的座位,lastfree向左找新的空闲位置,让13去新的座位坐

7要坐自己的位置。这个过程中,5的next  重新设置为指向13 的2

参考和引用

图片和主要内容来自

构建Lua解释器Part4:Table设计与实现 (manistein.github.io)

如果侵权,请联系我删除

  • 16
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值