HashTable使用手冊(cè)篇

書上的開篇是簡單介紹鏈表和數(shù)組了,想起自己當(dāng)年鸠项,c語言數(shù)據(jù)結(jié)構(gòu)敲起來手到拈來,各種隨便姿勢(shì)敲子姜,php弄久了祟绊,相當(dāng)生澀楼入。找時(shí)間且切題,數(shù)據(jù)結(jié)構(gòu)敲一遍牧抽,應(yīng)該很快回暖吧嘉熊。(沒人教,自己探索了這么久扬舒,才慢慢理解這東西的進(jìn)階路線阐肤,如果有會(huì)的人帶,不至于想現(xiàn)在這樣讲坎,再重拾c語言孕惜,這晃,就1年光景)

zend內(nèi)核的核心存儲(chǔ)結(jié)構(gòu)晨炕,就是HashTable了衫画。

初始化并創(chuàng)建一個(gè)hashtable: zend_hash_init(

HashTable *ht,

uint nSize,//大小會(huì)自動(dòng)被更改成最接近的,并且大于nSize的2的冪的值

hash_func_t pHashFunction,//NULL

dtor_func_t pDestructor,

/*回調(diào)函數(shù),當(dāng)刪除hashtable中的一個(gè)元素時(shí)候瓮栗,就會(huì)調(diào)用削罩,函數(shù)原型void method_name(voidpElement);pElment指向你要?jiǎng)h除的元素

zend_bool persistent //這是標(biāo)記是否持久化內(nèi)存,引擎會(huì)傳遞給pemalloc。有一個(gè)使用的例子:在php在請(qǐng)求最開始,初始化全局變量時(shí)候:

zend_hash_init(&EG(symbol_table),50,NULL,ZVAL_PTR_DTOR,0),50不是2的冪费奸,會(huì)被更改成64(zend/zend_execute_API.c)

#define ZVAL_PTR_DTOR (void (*)(void *)) zval_ptr_dtor_wrapper  (zend/zend_variables.h)

由此可見弥激,如果刪除hashtable的元素,比如unset(),時(shí)候愿阐,就會(huì)調(diào)用這個(gè)ZVAL_PTR_DTOR

*/

)

添加||修改

常用的有4個(gè)函數(shù)

int zend_hash_add(

HashTable *ht, //待操作的ht

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

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

void **pData, //要插入的數(shù)據(jù)换况,注意它是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

);

前兩個(gè)是關(guān)聯(lián)數(shù)組的舒裤,后兩個(gè)是普通數(shù)組(就是字符串索引或者數(shù)字的順序索引)

前兩個(gè) :update和add的區(qū)別呢,就是如果add發(fā)現(xiàn)已經(jīng)存在的數(shù)據(jù)觉吭,直接return腾供,但是update會(huì)修改

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

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

后兩個(gè): zend_hash_next_index_insert會(huì)自己計(jì)算出下一個(gè)index的索引值,因此不需要索引參數(shù)鲜滩。如果需要下一個(gè)的索引值伴鳖,可以用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內(nèi)添加一個(gè)新值,并且提取出來
  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; //理論不發(fā)生
  }
  if(zend_hash_index_find(ht,targetID,(void **)&data2) == FAILURE){
    return; //理論不可能  
  }
  此處的data1 != data2,但*data1 == *data2徙硅。即他們的值相同榜聂,但是地址不同,因?yàn)閔ashtable的更新值嗓蘑,是把要插入的數(shù)據(jù)(data1)copy一份须肆。所以hash桶存的指針與data1穿來的指針分別是兩個(gè)獨(dú)立的空間
}

檢查數(shù)據(jù)是否存在:
int zend_hash_exists(HashTable *ht,char *arKey,uint nKeyLen);
int zend_hash_index_exists(HashTable *ht,ulong h);
這兩個(gè)函數(shù)都不會(huì)返回SUCCESS/FAILURE 匿乃,只有0和1

if(zend_hash_exists(EG(active_symbol_table,"foo",sizeof("foo")))){
}
else{
}
這段代碼等價(jià)與 isset($foo)    所以這里是當(dāng)前符號(hào)表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是成員占的字節(jié)數(shù)豌汇,對(duì)于用戶空間的hash變量幢炸,則為sizeof(zval *)。b中的每個(gè)元素會(huì)拷貝到a中去拒贱,并且由pCopyConstructor函數(shù)進(jìn)行處理宛徊。對(duì)于數(shù)組變量這種類型的數(shù)據(jù),是用引用計(jì)數(shù)的方式逻澳,不是直接銷毀闸天。

zend_hash_merge和zend_hash_copy的唯一區(qū)別是,多一個(gè)int overwrite參數(shù)赡盘,表示是否覆蓋

void *tmp, uint size, int overwrite);

還有一種方式号枕,是選擇性拷貝,自定義一個(gè)函數(shù)進(jìn)行選擇性拷貝: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);//這是函數(shù)原型 

zend_bool  choice(HashTable *ht,void *pData,zend_hash_key *hash_key,void *pPrama){ //這里進(jìn)行選擇
    return (hash_key->arKey && hash_key->nKeyLength); //通過一個(gè)key和長度確定一個(gè)元素(可以看看hash_key的結(jié)構(gòu))
}

void merge_func(HashTable *a,HashTable *b){
  zend_hash_merge_ex(HashTable *a,HashTable *b,zval_add_ref,sizeof(zval *),choice,NULL);
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末陨享,一起剝皮案震驚了整個(gè)濱河市葱淳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌抛姑,老刑警劉巖赞厕,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異定硝,居然都是意外死亡皿桑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門蔬啡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诲侮,“玉大人,你說我怎么就攤上這事箱蟆」敌鳎” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵空猜,是天一觀的道長绽慈。 經(jīng)常有香客問我,道長辈毯,這世上最難降的妖魔是什么坝疼? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮谆沃,結(jié)果婚禮上钝凶,老公的妹妹穿的比我還像新娘。我一直安慰自己管毙,他們只是感情好腿椎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布桌硫。 她就那樣靜靜地躺著夭咬,像睡著了一般啃炸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上卓舵,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天南用,我揣著相機(jī)與錄音,去河邊找鬼掏湾。 笑死裹虫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的融击。 我是一名探鬼主播筑公,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼尊浪!你這毒婦竟也來了匣屡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤拇涤,失蹤者是張志新(化名)和其女友劉穎捣作,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鹅士,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡券躁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了掉盅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片也拜。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖趾痘,靈堂內(nèi)的尸體忽然破棺而出慢哈,到底是詐尸還是另有隱情,我是刑警寧澤扼脐,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布岸军,位于F島的核電站,受9級(jí)特大地震影響瓦侮,放射性物質(zhì)發(fā)生泄漏艰赞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一肚吏、第九天 我趴在偏房一處隱蔽的房頂上張望方妖。 院中可真熱鬧,春花似錦罚攀、人聲如沸党觅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杯瞻。三九已至镐牺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間魁莉,已是汗流浹背睬涧。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留旗唁,地道東北人畦浓。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像检疫,于是被迫代替她去往敵國和親讶请。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容