您的位置:首页 > 编程语言 > Lua

Lua5.2.3源码阅读(2)-Table

2015-07-14 23:28 555 查看
转载:http://blog.csdn.net/murisly/article/details/46869805

table在lua中是一个重要的数据结构,使用起来非常灵活,可以用它表示通常的array,map,set等结构。在分析源码之前,先看看table的一些特性。

(1). table是个key-value数组,索引key可以是数字,也可以是字符串。

(2). Key为数字时,默认下表从1开始(c/c++从0开始)

(3). table大小可以动态变化

(4). Lua5.2.3中table有7个成员函数(concat,insert,move,pack,remove,sort,unpack)

Lua中table定义如下(lobject.h)。

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">union</span> TKey {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> {
TValuefields;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Node *next;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* for chaining */</span>
} nk;
TValue tvk;
} TKey;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Node {
TValue i_val;
TKey i_key;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//保存有下一个指针</span>
} Node;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Table {
CommonHeader;
lu_byte flags;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 1<<p means tagmethod(p) is not present */</span>
lu_byte lsizenode;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* log2 of size of `node' array hash的大小(为2的整数次幂,这里表示的是幂次)*/</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> Table *metatable;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 元表 */</span>
TValue *<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">array</span>;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* array part 数组部分*/</span>
Node *node;     <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//hash表</span>
Node *lastfree;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* any free position is before this position */</span>
GCObject *gclist;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> sizearray;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* size of `array' array 数组的长度信息*/</span>
} Table;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li></ul>

Commonheader如上一篇介绍,包含链表指针,数据类型,回收状态。Table分为连个部分,数组部分和key-value部分。数组部分不需要保存键值,这部分在底层实现,是使用者看来只是透明的。在往表中插入数值时,table会根据key-value当前的状态动态地使用这两个部分。数组部分保存的是索引 (0
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> TValue *luaH_get (Table *t, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> TValue *key) {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">switch</span> (ttype(key)) {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> LUA_TSHRSTR: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> luaH_getstr(t, rawtsvalue(key));
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> LUA_TNIL: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> luaO_nilobject;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> LUA_TNUMBER: {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> k;
lua_Number n = nvalue(key);
lua_number2int(k, n);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (luai_numeq(cast_num(k), n)) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* index is int? */</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> luaH_getint(t, k);  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* use specialized version key为数组情况 */</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* else go through */</span>
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">default</span>: {
Node *n = mainposition(t, key);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">do</span> {  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* check whether `key' is somewhere in the chain */</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (luaV_rawequalobj(gkey(n), key))
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> gval(n);  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* that's it */</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> n = gnext(n);
} <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (n);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> luaO_nilobject;
}
}
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

(1) 当查找的key是字符串时,具体有luaH_getstr函数执行。该函数首先计算字符串的hash值,然后将hash值通过lmod方法映射到hash表中的位置,再在该位置的node*链表中查找该字符串。找到返回TValue,未找到返回nil。

(2) 当查找的key为nil时,直接返回nil。

(3) 当查找的key为数字时,调用luaH_getint,该函数如下
<code class="hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">const TValue <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*luaH_getint</span> (Table <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*t</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> key) {
<span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">/* (1 <= key && key <= t->sizearray) */</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (cast(unsigned <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, key-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) < cast(unsigned <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>, t->sizearray))
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> &t->array[key-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
lua_Number nk = cast_num(key);
Node <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*n</span> = hashnum(t, nk);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">do</span> {  <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">/* check whether `key' is somewhere in the chain */</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (ttisnumber(gkey(n)) && luai_nume<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">q(nvalue(gkey(n)</span>), nk))
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> gval(n);  <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">/* that's it */</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> n = gnext(n);
} <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (n);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> luaO_nilobject;
}
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>

如果key在(1,sizearray)之间,则直接返回array[key-1]。如果不在这个区间,则计算key的hash值,然后在对应的node*链中去查找。找到返回TValue,未找到返回nil。

(4) 对于其他的类型,都是先计算hash值,然后找到相应的node*位置,然后在该链中去查找。

3 table的赋值 luaH_set函数
<code class="hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">TValue <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*luaH_set</span> (lua_State <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*L</span>, Table <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*t</span>, const TValue <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*key</span>) {
const TValue <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*p</span> = luaH_get(t, key);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (p != luaO_nilobject)
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> cast(TValue <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*,</span> p);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> luaH_newkey(L, t, key);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

luaH_set首先查找,如果找到,直接返回key的指针。如果未找到,调用luaH_newkey函数,新建一个key,函数如下。
<code class="hljs applescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">/*
** inserts a new key <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">into</span> a hash table; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">first</span>, check whether key's main
** position <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> free. If <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span>, check whether colliding node <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">its</span> main
** position <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">or</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span>: <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">it</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span>, move colliding node <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> an empty place <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span>
** <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">put</span> new key <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">its</span> main position; otherwise (colliding node <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">its</span> main
** position), new key goes <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> an empty position.
** 新建一个KEY,值为nil
*/
TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
Node *mp;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (ttisnil(key)) luaG_runerror(L, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"table index is nil"</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (ttisnumber(key) && luai_numisnan(L, nvalue(key)))
luaG_runerror(L, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"table index is NaN"</span>);
mp = mainposition(t, key);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!ttisnil(gval(mp)) || isdummy(mp)) {  /* main position <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> taken? */
Node *othern;
Node *n = getfreepos(t);  /* <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">get</span> a free place */
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (n == NULL) {  /* cannot find a free place? */
rehash(L, t, key);  /* grow table */
/* whatever called 'newkey' take care <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">of</span> TM cache <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> GC barrier */
<span class="hljs-command" style="box-sizing: border-box;">      return</span> luaH_set(L, t, key);  /* insert key <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">into</span> grown table */
}
lua_assert(!isdummy(n));
othern = mainposition(t, gkey(mp));
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (othern != mp) {  /* <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> colliding node <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">out of</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">its</span> main position? */
/* yes; move colliding node <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">into</span> free position */
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (gnext(othern) != mp) othern = gnext(othern);  /* find previous */
gnext(othern) = n;  /* redo <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> chain <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">with</span> `n' <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> place <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">of</span> `mp' */
*n = *mp;  /* <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">copy</span> colliding node <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">into</span> free pos. (mp->next also goes) */
gnext(mp) = NULL;  /* now `mp' <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> free */
setnilvalue(gval(mp));
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {  /* colliding node <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">is</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">its</span> own main position */
/* new node will go <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">into</span> free position */
gnext(n) = gnext(mp);  /* chain new position */
gnext(mp) = n;
mp = n;
}
}
setobj2t(L, gkey(mp), key);
luaC_barrierback(L, obj2gco(t), key);
lua_assert(ttisnil(gval(mp)));
<span class="hljs-command" style="box-sizing: border-box;">  return</span> gval(mp);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li></ul>

(1)首先判断key是不是空,为空的话出错

(2)调用mainposition找到主位置mp,主位置即key的hash映射到表中的位置

(3)如果主位置为空,那么直接将key放到主位置。如果主位置不为空,那么先通过getfreepos函数找到一个空闲的位置n(这个位置从末尾开始找)。如果找不到空闲位置,就要调用rehash重新调整hash表,调整好后调用luaH_set设置。如果找到空闲位置,计算mp的主位置othern。如果两个不相等,即mp的主位置不在mp指向的这里,那么mp移到n,并将n放在mp的主位置链上。如果两个相等,即mp的主位置就是这里,将key赋值给n,然后将n放到mp的主位置链上。
这里简单的模拟一下,素组代表hash表,采用取模方式获得hash位置,Last指向最后空余位置。



加入14,17。



加入27,发现主位置7不为空,判断17的主位置也在7,将27赋给位置0,将17的next指向0。



加入30,返现0位置不为空,同时27的主位置不在0,将27移到最后的lastfree,将30赋给0位置。



加入15



加入25,发现主位置5不为空,15的主位置也在5,将25赋给lastfree,将15next指向位置8。

版权声明:本文为博主原创文章,未经博主允许不得转载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: