lua-设计与实现-4表

1 表

typedef struct Table {
  CommonHeader;
  //表示这个表中提供了哪些元方法 最开始这个flags 的,也就是 ,当查找一次之后,如果该表中存在某个元方法
  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */ 
  lu_byte lsizenode;  /* log2 of size of `node' array *///散列桶数组的大小的 log2(size)
  struct Table *metatable;
  TValue *array;  /* array part */
  Node *node;	//散列桶数组起始位置的指针
  Node *lastfree;  /* any free position is before this position *///散列桶数组最后位置的指针
  GCObject *gclist; //GC相关的链表
  int sizearray;  /* size of `array' array */
} Table;
  • 桶中链地址实现的单链表靠key关联

确定数组部分大小的标准是什么呢?

  • 希望在调整过后,**数组在每一个2次方位置(1开始)容纳的元素数量都超过该范围的50% ** (认为这个数组范围发挥了最大的效率)

未解疑问

  • 如何触发rehash。(代码逻辑是mainPositions没有free-nil位置触发,待求证)
  • hash部分的表查询如果实现??

nums数组解释:

// 只有利用率超过50%的数组元素会进入数组,否则进去hash
static int computesizes (int nums[], int *narray) {
  int i;
  int twotoi;  /* 2^i */
  int a = 0;  /* number of elements smaller than 2^i */
  int na = 0;  /* number of elements to go to array part */
  int n = 0;  /* optimal size for array part */

  // 这个循环完毕后,最重要的na存放的是数组部分的数据数量,而n是
  // na满足这个条件:在
  for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
    if (nums[i] > 0) {
      // 加上当前数量
      a += nums[i];
      // 如果数量已经超过半数, 那么数组的尺寸可以设置为这个大小
      if (a > twotoi/2) {  /* more than half elements present? */
        n = twotoi;  /* optimal size (till now) */
        // 记录下当前的数组大小
        na = a;  /* all elements smaller than n will go to array part */
      }
    }
    if (a == *narray) break;  /* all elements already counted */
  }
  *narray = n;
  lua_assert(*narray/2 <= na && na <= *narray);
  return na;
}

举例:
1,2,5,7,8,9
数组部分的长度为4时,就不符合大于50%的使用率了。(只有1,2落入数组)

表查找

在数组部分查找数据:

  • 查找成功,返回该key 的下一个数据

否则在散列桶部分查找数据:

  • 查找成功,返回该key 的下一个数据
  • 注意点:
    1,key为1,1.0这两种情况,如何确保算出的hash值一样。答:底层都是用double来表示number。

2 扩展笔记

2.1 表"#"特性总结

  • 对数组table,#取长度,底层直接获取(此时的前提是hash部分的头部node为nil),并不是遍历 (时间复杂度O(1))--luaH_getn
  • 对混合型table,#取长度,结果不可靠。 并不是返回前面数组的长度(这是误解,而是根据元素情况不定,可能会使用二分查找遍历或者其他--具体不纠缠)
    Lua源码阅读笔记 - table的长度

总结:

数组在每一个2次方位置(1开始)容纳的元素数量都超过该范围的50%

表的hash部分和C#的Dictionary原理大同小异

对数组table,#取长度,底层直接获取 -时间复杂度O(1)

对混合型table,#取长度,结果不可靠。

原文地址:https://www.cnblogs.com/Jaysonhome/p/13420211.html