zoukankan      html  css  js  c++  java
  • Zend Hash table 详解--转

    原文地址:http://www.phppan.com/2009/12/zend-hashtable/

    在PHP的Zend引擎中,有一个数据结构非常重要,它无处不在,是PHP数据存储的核心,各种常量、变量、函数、类、对象等都用它来组织,这个数据结构就是HashTable。

    HashTable在通常的数据结构教材中也称作散列表,哈希表。其基本原理比较简单(如果你对其不熟悉,请查阅随便一本数据结构教材或在网上搜 索),但PHP的实现有其独特的地方。理解了HashTable的数据存储结构,对我们分析PHP的源代码,特别是Zend Engine中的虚拟机的实现时,有很重要的帮助。它可以帮助我们在大脑中模拟一个完整的虚拟机的形象。它也是PHP中其它一些数据结构如数组实现的基 础。

    Zend HashTable的实现结合了双向链表向量(数组)两种数据结构的优点,为PHP提供了非常高效的数据存储和查询机制。

    一、 HashTable的数据结构

    在Zend Engine中的HashTable的实现代码主要包括zend_hash.h, zend_hash.c这两个文件中。Zend HashTable包括两个主要的数据结构,其一是Bucket(桶)结构,另一个是HashTable结构。Bucket结构是用于保存数据的容器,而 HashTable结构则提供了对所有这些Bucket(或桶列)进行管理的机制

    typedef struct bucket {
    	ulong h;						/* Used for numeric indexing */
    	uint nKeyLength;                /* key长度 */
    	void *pData;                    /* 指向Bucket中保存的数据的指针 */
    	void *pDataPtr;                 /* 指针数据 */
    	struct bucket *pListNext;       /* 指向HashTable桶列中下一个元素 */
    	struct bucket *pListLast;       /* 指向HashTable桶列中前一个元素 */
    	struct bucket *pNext;           /* 指向具有同一个hash值的桶列的后一个元素 */
    	struct bucket *pLast;           /* 指向具有同一个hash值的桶列的前一个元素 */
    	const char *arKey;              /* 必须是最后一个成员,key名称*/
            /* 旧版 char arKey[1];       必须是最后一个成员,key名称*/
    } Bucket;    

    在Zend HashTable中,每个数据元素(Bucket)有一个键名(key),它在整个HashTable中是唯一的,不能重复。根据键名可以唯一确定 HashTable中的数据元素。键名有两种表示方式。

    • 第一种方式使用字符串arKey作为键名,该字符串的长度为nKeyLength。注意到在上面的 数据结构中arKey虽然只是一个长度为1的字符数组,但它并不意味着key只能是一个字符。实际上Bucket是一个可变长的结构体,由于arKey是 Bucket的最后一个成员变量,通过arKey与nKeyLength结合可确定一个长度为nKeyLength的key。这是C语言编程中的一个比较 常用的技巧。
    • 另一种键名的表示方式是索引方式,这时nKeyLength总是0,长整型字段h就表示该数据元素的键名。
    • 简单的来说,即如果 nKeyLength=0,则键名为h;否则键名为arKey, 键名的长度为nKeyLength

    当nKeyLength > 0时,并不表示这时的h值就没有意义。事实上,此时它保存的是arKey对应的hash值。

    不管hash函数怎么设计,冲突都是不可避免的,也就是说不同的arKey可能有相同的hash值。

    具有相同hash值的Bucket保存在HashTable的arBuckets数组(参考下面的解释)的同一个索 引对应的桶列中。这个桶列是一个双向链表,其前向元素,后向元素分别用pLast, pNext来表示。新插入的Bucket放在该桶列的最前面。

    在Bucket中,实际的数据是保存在pData指针指向的内存块中,通常这个内存块是系统另外分配的。但有一种情况例外,就是当Bucket保存的数据是一个指针时,HashTable将不会另外请求系统分配空间来保存这个指针,而是直接将该指针保存到pDataPtr中,然后再将pData指向 本结构成员的地址。这样可以提高效率,减少内存碎片。由此我们可以看到PHP HashTable设计的精妙之处。如果Bucket中的数据不是一个指针,pDataPtr为NULL

    HashTable中所有的Bucket通过pListNext, pListLast构成了一个双向链表。最新插入的Bucket放在这个双向链表的最后。

    注意在一般情况下,Bucket并不能提供它所存储的数据大小的信息。所以在PHP的实现中,Bucket中保存的数据必须具有管理自身大小的能力。

  • 相关阅读:
    set集合 浅层拷贝会和深层拷贝
    "is"与"=="
    元组和字典
    运算符和列表
    Python 基础语法
    supervisor 安装配置详解
    如何运行vue项目
    过目不忘JS正则表达式
    vue Bus总线
    Robot Framework 环境安装(一)
  • 原文地址:https://www.cnblogs.com/thrillerz/p/4270713.html
Copyright © 2011-2022 走看看