从一个简易的哈希表入手,会让你更好的理解php的哈希表,他们的本质是一样的,只是php的哈希表做了更多的功能扩展,php的哈希表是php语言的一个重要核心,大量的内核代码使用到哈希表。

 #include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define HASH_ADD 0
#define HASH_UPDATE 1 typedef unsigned long ulong;
typedef unsigned int uint; typedef struct bucket {
ulong h; //字符数组的key哈希值或者数字数组的key值
uint nKeyLength;//字符数组的key长度,数字数组为0
void *pData;//存储的数据
struct bucket *pListNext;//在哈希表中的下一个元素
struct bucket *pListLast;//在哈希表中的下一个元素
struct bucket *pNext;//哈希值冲突时,同一哈希值链表的下一个元素
struct bucket *pLast;//哈希值冲突时,同一哈希值链表的上一个元素
const char *arKey;//字符数组的key值,数字数组为NULL
} Bucket; typedef struct _hashtable {
uint nTableSize;//哈希表的大小
uint nTableMask;//用来计算哈希值所在当前哈希表的位置
uint nNumOfElements;//哈希表的元素数量
ulong nNextFreeElement;//下一个自动插入的位置
Bucket *pListHead;//哈希表的第一个元素
Bucket *pListTail;//哈希表的最后一个元素
Bucket **arBuckets;//哈希表存储数据的数组
} HashTable; int hash_init(HashTable *ht, uint nSize);
int hash_add(HashTable *ht, const char *arKey, uint nKeyLength, void *pData);
int hash_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData);
int _hash_add_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, int flag);
int hash_index_add(HashTable *ht, ulong h, void *pData);
int hash_index_update(HashTable *ht, ulong h, void *pData);
int hash_foreach(HashTable *ht);
static int hash_resize_if_full(HashTable *ht);
int hash_resize(HashTable *ht);
char * hash_find(HashTable *ht,const char *arKey);
char * hash_index_find(HashTable *ht,ulong h); int hash_init(HashTable *ht, uint nSize){
uint i = ; if (nSize >= 0x80000000) {
/* prevent overflow */
ht->nTableSize = 0x80000000;
} else {
while ((1U << i) < nSize) {
i++;
}
ht->nTableSize = << i;
}
ht->nTableMask = ht->nTableSize - ;
ht->nNumOfElements = ;
ht->nNextFreeElement = ;
ht->pListHead = NULL;
ht->pListTail = NULL;
ht->arBuckets = (Bucket **)calloc(ht->nTableSize,sizeof(Bucket *));
return ;
} static inline ulong hash_func(const char *arKey, uint nKeyLength)
{
register ulong hash = ; /* variant with the hash unrolled eight times */
for (; nKeyLength >= ; nKeyLength -= ) {
hash = ((hash << ) + hash) + *arKey++;
hash = ((hash << ) + hash) + *arKey++;
hash = ((hash << ) + hash) + *arKey++;
hash = ((hash << ) + hash) + *arKey++;
hash = ((hash << ) + hash) + *arKey++;
hash = ((hash << ) + hash) + *arKey++;
hash = ((hash << ) + hash) + *arKey++;
hash = ((hash << ) + hash) + *arKey++;
}
switch (nKeyLength) {
case : hash = ((hash << ) + hash) + *arKey++; /* fallthrough... */
case : hash = ((hash << ) + hash) + *arKey++; /* fallthrough... */
case : hash = ((hash << ) + hash) + *arKey++; /* fallthrough... */
case : hash = ((hash << ) + hash) + *arKey++; /* fallthrough... */
case : hash = ((hash << ) + hash) + *arKey++; /* fallthrough... */
case : hash = ((hash << ) + hash) + *arKey++; /* fallthrough... */
case : hash = ((hash << ) + hash) + *arKey++; break;
case : break;
}
return hash;
} int hash_add(HashTable *ht, const char *arKey, uint nKeyLength, void *pData){
return _hash_add_update(ht, arKey, nKeyLength, pData, HASH_ADD);
} int hash_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData){
return _hash_add_update(ht, arKey, nKeyLength, pData, HASH_UPDATE);
} int _hash_add_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, int flag){
Bucket *p;
ulong h;
ulong nIndex;
h = hash_func(arKey, nKeyLength);
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
//printf("nIndex=>%d,arKey=>%s,p=>%s,%s\n",nIndex,arKey,p->arKey,p->pData);
if (p->arKey == arKey){
if(flag == HASH_ADD){
//已经存在同样的key
return -;
}else{
p->pData = pData;
return ;
}
}
p = p->pNext;
}
p = (Bucket *)malloc(sizeof(Bucket));
p->h = h;
p->nKeyLength = nKeyLength;
p->pData = pData;
p->pNext = ht->arBuckets[nIndex];
p->pLast = NULL;
if(p->pNext != NULL){
p->pNext->pLast = p;
}
p->arKey = arKey;
ht->arBuckets[nIndex] = p;
ht->nNumOfElements++;
if(ht->pListHead == NULL){
ht->pListHead = p;
p->pListNext = NULL;
p->pListLast = NULL;
ht->pListTail = p;
}else{
p->pListLast = ht->pListTail;
p->pListLast->pListNext = p;
p->pListNext = NULL;
ht->pListTail = p;
}
hash_resize_if_full(ht);
return ;
} int hash_index_add(HashTable *ht, ulong h, void *pData){
return _hash_index_add_update(ht,h,pData,HASH_ADD);
} int hash_index_update(HashTable *ht, ulong h, void *pData){
return _hash_index_add_update(ht,h,pData,HASH_UPDATE);
} int hash_next_add(HashTable *ht,void *pData){
ulong h = ht->nNextFreeElement;
return _hash_index_add_update(ht,h,pData,HASH_ADD);
} int _hash_index_add_update(HashTable *ht, ulong h,void *pData,int flag){
Bucket *p;
ulong nIndex;
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
if (p->arKey == NULL && p->nKeyLength == ){
if(flag == HASH_ADD){
//已经存在同样的key
return -;
}else{
p->pData = pData;
return ;
}
}
p = p->pNext;
}
p = (Bucket *)malloc(sizeof(Bucket));
p->h = h;
p->nKeyLength = ;
p->pData = pData;
p->pNext = ht->arBuckets[nIndex];
p->pLast = NULL;
if(p->pNext != NULL){
p->pNext->pLast = p;
}
p->arKey = NULL;
ht->arBuckets[nIndex] = p;
ht->nNumOfElements++;
if(h >= ht->nNextFreeElement){
ht->nNextFreeElement = h + ;
}
if(ht->pListHead == NULL){
ht->pListHead = p;
p->pListNext = NULL;
p->pListLast = NULL;
ht->pListTail = p;
}else{
p->pListLast = ht->pListTail;
p->pListLast->pListNext = p;
p->pListNext = NULL;
ht->pListTail = p;
}
hash_resize_if_full(ht);
return ;
} int hash_foreach(HashTable *ht){
if(ht->pListHead == NULL){
return ;
}
Bucket *p;
p = ht->pListHead;
while(p != NULL){
if(p->nKeyLength > ){
printf("h=>%ld,index=>%ld,%s=>%s\n",p->h,p->h & ht->nTableMask,p->arKey,p->pData);
}else{
printf("h=>%ld,index=>%ld,%d=>%s\n",p->h,p->h & ht->nTableMask,p->h,p->pData);
}
p=p->pListNext;
}
} static int hash_resize_if_full(HashTable *ht){
//printf("if_null,num=>%d,size=>%d\n",ht->nNumOfElements,ht->nTableSize);
if(ht->nNumOfElements >= ht->nTableSize){
return hash_resize(ht);
}
} int hash_resize(HashTable *ht){
printf("before resize:%d\n",ht->nTableSize);
hash_foreach(ht);
ht->nTableSize = ht->nTableSize << ;
ht->nTableMask = ht->nTableSize - ;
Bucket **t;
t = realloc(ht->arBuckets,ht->nTableSize * sizeof(Bucket*));
memset(t,,ht->nTableSize * sizeof(Bucket *));
ht->arBuckets = t;
Bucket *p;
ulong nIndex;
for(p=ht->pListHead;p!=NULL;p=p->pListNext){
nIndex = p->h & ht->nTableMask;
p->pNext = ht->arBuckets[nIndex];
if(p->pNext != NULL){
p->pNext->pLast = p;
}
ht->arBuckets[nIndex] = p;
}
printf("after resize:%d\n",ht->nTableSize);
hash_foreach(ht);
return ;
} char * hash_find(HashTable *ht,const char *arKey){
ulong h;
int nKeyLength = strlen(arKey);
h = hash_func(arKey, nKeyLength);
ulong nIndex = h & ht->nTableMask;
Bucket *p;
for(p=ht->arBuckets[nIndex];p!=NULL;p=p->pNext){
if(strcmp(p->arKey,arKey) == && p->nKeyLength == nKeyLength){
return p->pData;
}
printf("hash_find,arKey=>%s,nKeyLength=>%d,pData=>%s\n",p->arKey,p->nKeyLength,p->pData);
}
return NULL;
} char * hash_index_find(HashTable *ht,ulong h){
ulong nIndex = h & ht->nTableMask;
Bucket *p;
for(p=ht->arBuckets[nIndex];p!=NULL;p=p->pNext){
if(p->nKeyLength == && p->arKey == NULL){
return p->pData;
}
}
} int main(){
HashTable *ht;
ht = (HashTable *)malloc(sizeof(HashTable));
hash_init(ht,);//初始化哈希表,nTableSize=1
char *arKey = "keya";
int len = strlen(arKey);
char *pData = "valuea";
hash_add(ht,arKey,len,pData);//插入字符串数据
arKey = "keyb";
len = strlen(arKey);
pData = "valueb";
hash_add(ht,arKey,len,pData);
arKey = "keyb";
len = strlen(arKey);
pData = "valueb";
int ret = hash_add(ht,arKey,len,pData);//插入失败,key已经存在
printf("ret=>%d\n",ret);
char c;
//char buffer[100];
char *buffer;
for(c='c';c<='z';c++){
buffer = (char *)malloc();
sprintf(buffer,"key%c",c);
arKey = buffer;
len = strlen(arKey);
buffer = (char *)malloc();
sprintf(buffer,"value%c",c);
pData = buffer;
printf("%s,%s\n",arKey,pData);
hash_add(ht,arKey,len,pData);//批量插入
}
for(c='A';c<='Z';c++){
buffer = (char *)malloc();
sprintf(buffer,"value%c",c);
pData = buffer;
hash_next_add(ht,pData);//使用数字数组,自动插入元素,不需要指定key
}
hash_index_add(ht,,"index3");//使用数字数组,指定索引位置。
hash_next_add(ht,"");
hash_next_add(ht,"");
hash_index_update(ht,,"100 -> 102");//更新指定位置的值
hash_foreach(ht);//遍历数组
char *finda = hash_find(ht,"keya");//查找指定字符串key的值
printf("finda=>%s\n",finda);
char *findb = hash_index_find(ht,);//查找指定索引的值
printf("findb=>%s\n",findb);
}

php扩展开发-实现一个简易的哈希表的更多相关文章

  1. .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”

    FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...

  2. .NETCore 快速开发做一个简易商城

    介绍 上一篇介绍 <.NETCore 基于 dbfirst 体验快速开发项目>,讲得不太清楚有些多人没看懂.这次吸取教训,将一个简易商城做为案例,现实快速开发. 本案例用于演示或学习,不具 ...

  3. PHP扩展开发--编写一个helloWorld扩展

    为什么要用C扩展 C是静态编译的,执行效率比PHP代码高很多.同样的运算代码,使用C来开发,性能会比PHP要提升数百倍. 另外C扩展是在进程启动时加载的,PHP代码只能操作Request生命周期的数据 ...

  4. Jmeter扩展组件开发(2) - 扩展开发第一个demo的实现

    maven工程src目录介绍 main:写代码 main/java:写Java代码 main/resources:写配置文件 test:写测试代码 test/java demo实现 创建Package ...

  5. 使用angular.js开发的一个简易todo demo

    前沿 在CVTE实习考察的一周里,接触到了angular,并在最后的一天任务里要求使用angular做一个功能主要包括创建.编辑.恢复.删除以及留言的todo demo,并支持响应式布局.因为之前没怎 ...

  6. 自己封装的一个简易的二维表类SimpleTable

    在QT中,QTableWidget处理二维表格的功能很强大(QTableView更强大),但有时我们只想让它显示少量数据(文字和图片),这时,使用QTableWidget就有点不方便了(个人感觉).所 ...

  7. 使用Phalcon框架开发一个简易的博客系统

    使用Phalcon PHP框架开发一个简易的博客系统(类似于CMS) 最近在做Phalcon(Phalcon在英文中指的是鸟类中飞得最快的那一个物种,由于是高性能框架,借用了这个词)相关的项目,由于刚 ...

  8. [CareerCup] 8.10 Implement a Hash Table 实现一个哈希表

    8.10 Design and implement a hash table which uses chaining (linked lists) to handle collisions. 这道题让 ...

  9. visual Studio 2017 扩展开发(一)《向Visual Studio菜单栏新增一个菜单》

    最近有接触到关于visual studio 2017 扩展的开发,特此记录,也是为了督促自己去深入了解其原理. 开始开发Visual Studio 扩展,在这里我安装了visual studio 20 ...

随机推荐

  1. MS Chart 条状图【转】

    private void Form1_Load(object sender, EventArgs e) {            string sql1 = "select  类别,coun ...

  2. ORA-02298: 无法验证 (约束) - 未找到父项关键字 解决办法

    --在用PL/SQL导入表数据的时候报错 ORA-02298: 无法验证 (PNET.POST_CLOB_FK) - 未找到父项关键字 --发现是启用外键约束时报的错alter table DM_VO ...

  3. JavaSE之Java基础(4)

    16.String.StringBuilder和StringBuffer的区别 String类是final的,不可变,StringBuilder和StringBuffer可变: 大部分情况下的执行效率 ...

  4. The sixth day

    bound to 铁定You are bound to be fired  你会被铁定开除的 A:Dan forgot his map? Dan忘了带地图了吗? B:Yep!And he's boun ...

  5. 【Android开发笔记】杂项

    Android studio shift+enter : start new line Theme 将     <style name="AppBaseTheme" pare ...

  6. php-7.1.11编译选项配置

    ./configure \ --prefix=/usr/local/php-7.1.11 \ --with-config-file-path=/usr/local/php7.1.11/etc \ -- ...

  7. java Vamei快速教程18 容器

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Java中有一些对象被称为容器(container).容器中可以包含多个对象,每个 ...

  8. Python常见编程规范总结

    Pythonic定义 Python最常用的编码风格还是PEP8,详见:http://jython.cn/dev/peps/pep-0008/ Pythonic确实很难定义,先简单引用下<Pyth ...

  9. IOS UIApplication使用

    - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...

  10. IBM中国

    https://www.ibm.com/developerworks/cn/linux/l-memory/