美文网首页
HashTable使用手册篇

HashTable使用手册篇

作者: 等哈哈咯 | 来源:发表于2017-08-07 21:05 被阅读0次

    书上的开篇是简单介绍链表和数组了,想起自己当年,c语言数据结构敲起来手到拈来,各种随便姿势敲,php弄久了,相当生涩。找时间且切题,数据结构敲一遍,应该很快回暖吧。(没人教,自己探索了这么久,才慢慢理解这东西的进阶路线,如果有会的人带,不至于想现在这样,再重拾c语言,这晃,就1年光景)

    zend内核的核心存储结构,就是HashTable了。

    初始化并创建一个hashtable: zend_hash_init(

    HashTable *ht,

    uint nSize,//大小会自动被更改成最接近的,并且大于nSize的2的幂的值

    hash_func_t pHashFunction,//NULL

    dtor_func_t pDestructor,

    /*回调函数,当删除hashtable中的一个元素时候,就会调用,函数原型void method_name(voidpElement);pElment指向你要删除的元素

    zend_bool persistent //这是标记是否持久化内存,引擎会传递给pemalloc。有一个使用的例子:在php在请求最开始,初始化全局变量时候:

    zend_hash_init(&EG(symbol_table),50,NULL,ZVAL_PTR_DTOR,0),50不是2的幂,会被更改成64(zend/zend_execute_API.c)
    
    #define ZVAL_PTR_DTOR (void (*)(void *)) zval_ptr_dtor_wrapper  (zend/zend_variables.h)
    
    由此可见,如果删除hashtable的元素,比如unset(),时候,就会调用这个ZVAL_PTR_DTOR
    
    */
    
    )
    

    添加||修改

    常用的有4个函数

    int zend_hash_add(

    HashTable *ht, //待操作的ht

    char *arKey, //索引,如"my_key"

    uint nKeyLen, //字符串索引的长度,如6

    void **pData, //要插入的数据,注意它是void **类型的。int *p,i=1;p=&i,pData=&p;。

    uint nDataSize,

    void pDest //如果操作成功,则pDest=pData;

    );

    int zend_hash_update(

    HashTable *ht,

    char *arKey,

    uint nKeyLen,

    void *pData,

    uint nDataSize,

    void **pDest

    );

    int zend_hash_index_update(

    HashTable *ht,

    ulong h,

    void *pData,

    uint nDataSize,

    void **pDest

    );

    int zend_hash_next_index_insert(

    HashTable *ht,

    void *pData,

    uint nDataSize,

    void **pDest

    );

    前两个是关联数组的,后两个是普通数组(就是字符串索引或者数字的顺序索引)

    前两个 :update和add的区别呢,就是如果add发现已经存在的数据,直接return,但是update会修改

    使用例子: $foo['bar'] = "xxx";

    zend_hash_add(ht,"bar",sizeof("bar"),"xxx",sizeof("xxx"),NULL);

    后两个: zend_hash_next_index_insert会自己计算出下一个index的索引值,因此不需要索引参数。如果需要下一个的索引值,可以用ulong nextid = zend_hash_next_free_element(ht); 配合zend_hash_index_update(ht,nextid,&data,sizeof(data),NULL);

    查找索引值:

    int zend_hash_find(HashTable *ht,char *arKey,unit nKeyLen,void **pData);

    
    void  hash_sample(HashTable *ht, sample_data *data1){//往hashtable内添加一个新值,并且提取出来
      sample_data *data2;
      ulong targetID = zend_hash_next_free_element(ht);
      if(zend_hash_index_update(ht,targetID,data1,sizeof(sample_data),NULL)  == FAILURE){
         return; //理论不发生
      }
      if(zend_hash_index_find(ht,targetID,(void **)&data2) == FAILURE){
        return; //理论不可能  
      }
      此处的data1 != data2,但*data1 == *data2。即他们的值相同,但是地址不同,因为hashtable的更新值,是把要插入的数据(data1)copy一份。所以hash桶存的指针与data1穿来的指针分别是两个独立的空间
    }
    

    检查数据是否存在:
    int zend_hash_exists(HashTable *ht,char *arKey,uint nKeyLen);
    int zend_hash_index_exists(HashTable *ht,ulong h);
    这两个函数都不会返回SUCCESS/FAILURE ,只有0和1

    if(zend_hash_exists(EG(active_symbol_table,"foo",sizeof("foo")))){
    }
    else{
    }
    这段代码等价与 isset($foo)    所以这里是当前符号表active_symbol_table
    

    拷贝和合并

    void zend_hash_copy(HashTable *a,HashTabel *b,copy_ctor_func_t pCopyConstructor,void *tmp,unit size);
    

    tmp 在4.3以后为NULL,size是成员占的字节数,对于用户空间的hash变量,则为sizeof(zval *)。b中的每个元素会拷贝到a中去,并且由pCopyConstructor函数进行处理。对于数组变量这种类型的数据,是用引用计数的方式,不是直接销毁。

    zend_hash_merge和zend_hash_copy的唯一区别是,多一个int overwrite参数,表示是否覆盖

    void *tmp, uint size, int overwrite);
    

    还有一种方式,是选择性拷贝,自定义一个函数进行选择性拷贝:zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam);

    typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, void *source_data, zend_hash_key *hash_key, void *pParam);//这是函数原型 
    
    zend_bool  choice(HashTable *ht,void *pData,zend_hash_key *hash_key,void *pPrama){ //这里进行选择
        return (hash_key->arKey && hash_key->nKeyLength); //通过一个key和长度确定一个元素(可以看看hash_key的结构)
    }
    
    void merge_func(HashTable *a,HashTable *b){
      zend_hash_merge_ex(HashTable *a,HashTable *b,zval_add_ref,sizeof(zval *),choice,NULL);
    }
    
    

    相关文章

      网友评论

          本文标题:HashTable使用手册篇

          本文链接:https://www.haomeiwen.com/subject/aavalxtx.html