从一个简易的哈希表入手,会让你更好的理解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. PHP拾贝

    $_SERVER['DOCUMENT_ROOT']指向了web服务器文档树的根.(E:/wamp/www/) ********************************************* ...

  2. 【翻译转载】【官方教程】Asp.Net MVC4入门指南(2):添加一个控制器

    2. 添加一个控制器 · 原文地址:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-c ...

  3. 关于wav文件fft处理后x,y轴坐标数据的问题

    1.关于横坐标的频率的最大值是采样频率,那么每个点对应的频率值就很好算了:f(n) = [Fs/(N/2)]*n  (Fs是采样频率,常见的是44.1KHz(44100),N是采样点数,k表是第k个点 ...

  4. 处理 wait millis 60009, active 50 ,maxactive 200 异常 过程

    处理 wait millis 60009, active 50 ,maxactive 200 异常 过程2018年04月19日 16:48:46 守望dfdfdf 阅读数:1910 标签: druid ...

  5. Django--对表的操作

    一丶多表创建 1.创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之 ...

  6. weex 项目搭建

    第一步:安装依赖 npm install -g weex-toolkit weex -v //查看当前weex版本 weex update weex-devtool@latest //@后标注版本后, ...

  7. javascript HTML静态页面传值的四种方法

    一:JavaScript静态页面值传递之URL篇能过URL进行传值.把要传递的信息接在URL上.Post.htm 代码如下: <input type="text" name= ...

  8. badboy页面脚本发生错误,解决方案

    1.参考网址:https://jingyan.baidu.com/article/e9fb46e17537797520f76645.html?from=qqbrowser061108 本人亲自测试,方 ...

  9. js实现排序去重计算字符次数

    /*去重*/ var arr=[1,4,4,7,3,9,0,3,2,1,"你好","你","你好","你 "]; var ...

  10. 可以使用可用的服务和参数调用在“eWorld.WCFImplement.ServiceImplement.ImageArchiveService”类型上使用“Autofac.Core.Activators.Reflection.DefaultConstructorFinder”找到的构造函数: 无法解析参数'eWorld.WCFBLL.ImageArchive.IDocumentOperation

    可以使用可用的服务和参数调用在“eWorld.WCFImplement.ServiceImplement.ImageArchiveService”类型上使用“Autofac.Core.Activato ...