php7-hashtable总结
来源:互联网 发布:全职高手之烽火知韩 编辑:程序博客网 时间:2024/04/28 18:47
hashtable 结构
typedef struct _Hashtable { unit32_t nTableSize //最小为8,标准为大于实际元素个数的2次方,6->8,9->16 unit32_t nTableMask; //tablesize-1 unit32_t nNumUsed; //已使用的元素,当满了的时候会重构,去除已经unset的元素 unit32_t nNumOfElement; //实际存的个数 zend_long nNextFreeElement; //是下一个可以使用的数字键值,当你使用$array[] = xyz是被使用到。 Bucket *arData; //实际指向的数组,保存了所有的bukets数组元素 uint32_t *arHash //hash数组中查找索引为idx = ht->arHash[hash & ht->nTableMask] dtor_func_t pDestructor; uint32_t nInternalPointer; union { struct { ZEND_ENDIAN_LOHI_3( zend_uchar flags, zend_uchar nApplyCount, uint16_t reserve) } v; uint32_t flags; } u;} HashTable;
bucket结构
typedef struct _Bucket { zend_ulong h; //索引值 zend_string *key //字符串键 zval val //zavl结构内嵌进bucket,因此不用再申请内存} Bucket;
指针变量arData实际指向数组的头地址,数组在php7是被分配到了一块连续的内存中。arData数组以插入的顺序保存元素。所以第一个数组元素会保存在arData[0],第二元素在arData[1]等等。这跟元素对应的键没有任何关系,这只跟插入的顺序相关。
常见问题
1.Buckets不用再单独分配什么意思?
因为老的hashtable实现中,数组arData中存的是一个指向随机地址的Bucket结构体的指针,而新的实现是直接将bucket存入数组值中,也就是说之前arData[0]中只是存的bucket的地址,现在直接存bucket了。
2.Zvals不再单独分配,它会被直接嵌入到任何需要存放它的地方(例如,一个hashtable bucket中)。
同样的意思,之前bucket中是存的指向zval的一个指针,现在是直接将zval变量存进来,如果zval存的是简单类型的话,那就更方便了。
3.冲突处理链表现在用的是一个索引列表,并且每个索引是嵌入到zval中的
当bucket中的h和*key与实际查找的不对应时,那么应该是产生冲突了,新的索引列表是存在zval结构体中的u2联合体中,
union { uint32_t var_flags; uint32_t next; /* hash collision chain */ uint32_t cache_slot; /* literal cache slot */ uint32_t lineno; /* line number (for ast nodes) */ } u2;
可以通过idx = Z_NEXT(b->val);
查找出当前zval的下一个zval(处理冲突)
源码理解
解决冲突的代码如下:
zend_ulong h = zend_string_hash_val(key);unit32_t idx = ht->arHash[h & ht->nTableMask];while (idx != INVALID_IDX) { Bucket *b = &ht->arData[idx]; if(b->h = h && zend_string_equals(b->key,key)){ return b; } idx = Z_NEXT(b->val);}return NULL;
遍历数组的代码如下:
uint32_t i;for (i = 0; i < ht->nNumUsed; ++i) { Bucket *b = &ht->arData[i]; if (Z_ISUNDEF(b->val)) continue; // do stuff with bucket}
总结(部分摘自网络)
1.arData数组以插入的顺序保存元素。所以第一个数组元素会保存arData[0],第二元素在arData[1]等等。这跟元素对应的键没有任何关系,这只跟插入的顺序相关。所以如果你在hashtable中保存了5个元素,arData[0]到arData[4]的槽(slot)会被用到,下一个空闲槽是arData[5]。这个数字会记录在nNumUsed中,它们是一样的,不过仅仅只是在只执行插入操作的情况下。如果一个元素被从Hashtable中删除,我们肯定不想把arData数组中位于删除元素后面的元素都前移一位从而保持数组的连续性,相反我们只是将删除元素zval类型标记为IS_UNDEF。
2.实际上Hashtable的查找还是使用了arHash这个数组,这个数组由unit32_t类型的值组成。arHash数组跟arData的大小一样(都是nTableSize),并且都被分配了一段连续的内存区块。在hash数组中查找索引为idx = ht->arHash[hash & ht->nTableMask]的元素。这个索引对应的元素是冲突处理链表的头元素。所以ht->arData[idx]是我们要检查的第一个元素。如果这个元素中保存的键跟我们要查找的键相同,那么查找就搞定了。如果不的相同的话,则需要查找冲突处理链表的下一个元素,这个元素的索引保存在bucket->val.u2.next中,它保存在zval结构体中很少会用到的最后4个字节中。我们继续遍历这个链表(使用索引而不是指针)直到找到我们要找的bucket,或者是碰到INVALID_IDX——这意味着你要查找的key并不存在。
- php7-hashtable总结
- PHP7中新的Hashtable实现和性能改进
- Hashtable的遍历总结
- Hashtable的遍历总结
- Hashtable的遍历总结
- c# hashtable 操作总结
- hashSet,hashMap,hashTable总结
- Leetcode HashTable 题型总结
- Hashset,Hashtable,Hashmap总结
- hashmap 、hashtable、 ConcurrentHashMap总结
- php7
- php7
- 浅析PHP7新功能及语法变化总结
- PHP7的一些新特性总结
- Map,HashMap,Hashtable,TreeMap总结
- Hashtable和HashMap的总结
- HashTable
- Hashtable
- [P2680][NOIP2015]运输计划
- 查找mysql数据库文件位置
- 推荐五款管理工具(思维导图)
- ViewPager 无限轮播自动轮播
- [Atcoder CODE FESTIVAL 2017 qual C]D
- php7-hashtable总结
- NOIP模拟(10.23)T1 Fibonacci
- 【zookeeper】java API 例子
- Spring 中异常处理方法的总结
- 关于zigbee的一些不易注意的地方
- java学习第35天,新循环 泛型
- JAVA中的矩阵相乘(Math3的使用)
- 有史以来影响世界的颠覆性技术 | 未来的高附加值颠覆性技术产业
- 《自然》杂志:关于人类未来的工作,有三个最紧迫的问题