php扩展开发-实现一个简易的哈希表
从一个简易的哈希表入手,会让你更好的理解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扩展开发-实现一个简易的哈希表的更多相关文章
- .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”
FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...
- .NETCore 快速开发做一个简易商城
介绍 上一篇介绍 <.NETCore 基于 dbfirst 体验快速开发项目>,讲得不太清楚有些多人没看懂.这次吸取教训,将一个简易商城做为案例,现实快速开发. 本案例用于演示或学习,不具 ...
- PHP扩展开发--编写一个helloWorld扩展
为什么要用C扩展 C是静态编译的,执行效率比PHP代码高很多.同样的运算代码,使用C来开发,性能会比PHP要提升数百倍. 另外C扩展是在进程启动时加载的,PHP代码只能操作Request生命周期的数据 ...
- Jmeter扩展组件开发(2) - 扩展开发第一个demo的实现
maven工程src目录介绍 main:写代码 main/java:写Java代码 main/resources:写配置文件 test:写测试代码 test/java demo实现 创建Package ...
- 使用angular.js开发的一个简易todo demo
前沿 在CVTE实习考察的一周里,接触到了angular,并在最后的一天任务里要求使用angular做一个功能主要包括创建.编辑.恢复.删除以及留言的todo demo,并支持响应式布局.因为之前没怎 ...
- 自己封装的一个简易的二维表类SimpleTable
在QT中,QTableWidget处理二维表格的功能很强大(QTableView更强大),但有时我们只想让它显示少量数据(文字和图片),这时,使用QTableWidget就有点不方便了(个人感觉).所 ...
- 使用Phalcon框架开发一个简易的博客系统
使用Phalcon PHP框架开发一个简易的博客系统(类似于CMS) 最近在做Phalcon(Phalcon在英文中指的是鸟类中飞得最快的那一个物种,由于是高性能框架,借用了这个词)相关的项目,由于刚 ...
- [CareerCup] 8.10 Implement a Hash Table 实现一个哈希表
8.10 Design and implement a hash table which uses chaining (linked lists) to handle collisions. 这道题让 ...
- visual Studio 2017 扩展开发(一)《向Visual Studio菜单栏新增一个菜单》
最近有接触到关于visual studio 2017 扩展的开发,特此记录,也是为了督促自己去深入了解其原理. 开始开发Visual Studio 扩展,在这里我安装了visual studio 20 ...
随机推荐
- vs2017通过snippet代码片断进行标准化注释
我们在进行团队开发时,类的注释已经可以做到自定义了,详细看上篇文章<vs2017通过模块文件添加自定义注释>,而对于方法的注释,我们也需要完善一下,这里我们用到了“代码片断”插件,VS里有 ...
- Git远程推送文件太大的error解决
error: RPC failed; curl 56 OpenSSL SSL_read: SSL_ERROR_SYSCALL, errfno 10054 方法1: 改成ssh推送 方法2: 把推送的缓 ...
- 检查python以及django是否安装配置成功
首先说明下,我使用pycharm作为开发的IDE,在第一次创建django项目的时候,会自动安装django包的.(网上也有很多单独安装的方法),环境变量配置成功后,就是用下面的方法检测安装成功与否. ...
- 将vim配置成一个轻量的IDE开发工具
1.插件管理工具 2.安装插件 3.配置.vimrc 1.插件管理工具 vim的插件有很多,为了后面方便添加新的插件,我们需要一个插件管理工具来帮我们管理安装的插件,这里使用的是vim-pathoge ...
- Ubuntu 12.04搭建svn服务器【转】
这是一个比较老旧的话题,毕竟大家现在都使用Git(http://git-scm.com/),Git在分支.代码存储.冲突.速度方面的机制都更优秀. 那我们难道还有使用svn的场景?当然,比如对Git很 ...
- 使用CSS设置Chrome打印背景色
以下内容适用于Chrome浏览器 打印背景色可以通过在打印预览页面勾选背景图形实现 如果需要在用户不勾选的情况下依然能够打印背景色,可以通过css实现,如,table隔行设置背景色: .data-ta ...
- No module named 'revoscalepy'问题解决
SqlServer2017开始支持Python,前段时间体验了下,按照微软的入门例子操作的:https://microsoft.github.io/sql-ml-tutorials/python/re ...
- Android商城开发系列(十二)—— 首页推荐布局实现
首页新品推荐的布局效果如下图: 这块布局是使用LinearLayout和GridView去实现,新建recommend_item.xml,代码如下所示: <?xml version=" ...
- 【文件拷贝】使用Total Commander Portable拖动拷贝文件,支持队列
使用Total Commander Portable,可以批量拷贝多个位于相同或不同目录的文件(夹)到指定的相同或不同的目录.这样避免了同时复制多个大的文件造成的速度减慢:将所有任务手动操作之后,剩下 ...
- IOS 自定义Layer(图层)
方式1: @interface NJViewController () @end @implementation NJViewController - (void)viewDidLoad { [sup ...