lua版本:5.3.5
数据结构
table是lua唯一的数据结构,也是lua最明显的特色之一,使用者可以在table的基础上实现各种各样的数据结构。table即可以作为数组,又可以作为哈希表,而在实现上,源码里也是将table的内部存储分为了数组和哈希表。
/*
** Tables
*/
typedef union TKey {
struct {
TValuefields;
int next; /* for chaining (offset for next node) */
} nk;
TValue tvk;
} TKey;
typedef struct Node {
TValue i_val;
TKey i_key;
} Node;
typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of 'node' array */
unsigned int sizearray; /* size of 'array' array */
TValue *array; /* array part */
Node *node;
Node *lastfree; /* any free position is before this position */
struct Table *metatable;
GCObject *gclist;
} Table;
- TKey:哈希表里每个节点的key值,除了包含作为key的值,还指向同哈希值的下一个节点。
- Node:哈希表的内的每个节点,包含key和value。
- Table:表结构
- lsizenode:哈希表大小的log2(哈希表大小为2的幂次)。
- sizearray:数组大小(数组大小为2的幂次)。
- array:数组头部指针。
- node:哈希表头部指针。
- lastfree:指向哈希表内最后一个空着的节点。
- metatable:元表。
- gclist:用于垃圾回收。
结构本身很简单明晰,唯一需要多说下的是哈希表的结构,这里推荐篇文章。
简单来说,这是个闭散列表,TKey里指向的下一个节点就是哈希表内的节点,当新元素(new)的哈希值所指向的位置如果被占据,则检查该位置的老元素(old)是否应该在这:
- 如果old应在此处,则new找空位,并和old的next连接。
- 如果old不应该在此处,则old另找新位置,new占据此处。
实现
新增元素
/*
** inserts a new key into a hash table; first, check whether key's main
** position is free. If not, check whether colliding node is in its main
** position or not: if it is not, move colliding node to an empty place and
** put new key in its main position; otherwise (colliding node is in its main
** position), new key goes to an empty position.
*/
TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
Node *mp;
TValue aux;
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
else if (ttisfloat(key)) {
lua_Integer k;
if (luaV_tointeger(key,