hash表的简单说明以及例子
来源:互联网 发布:蒙奇奇淘宝旗舰店 编辑:程序博客网 时间:2024/06/05 07:08
http://blog.csdn.net/feixiaoxing/article/details/6885657 这一篇写的很赞
数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。hash表可以解决以上两个不足之处。
假如你要在图书馆里找一本《电路原理》,这本书首先它在工科类下面,再在工科类的电子信息这个分类里面,你首先要找到工科,再找到电子信息类,然后再找《电路原理》。好了,hashEntry_s相当于这个分类表,它的key就是你要查的类别,data就是你要查的书本,hashtable就是那张存放类别的大表。
struct hashEntry_s{void *key;void *data;struct hashEntry_s *next;};struct hashTable_s{ struct hashEntry_s **hashlist;}; typedef struct hashTable_s hashTable_t;
首先要生成这样hash表
HASHSIZE 最好是素数,这样可以减少冲突的概率。
hashlist指向各个分类
#define HASHSIZE 67hashTable_t *createHashTable(void){ hashTable_t *table; int i,len,primesize; table = malloc(sizeof(hashTable_t)); if(NULL == table){ printf("error in createtable"); return NULL; } len = sizeof(struct hashEntry_s *)*HASHSIZE; table->hashlist = malloc(len); if(table->hashlist == NULL){ printf("error in createtable\n"); exit(1); } for(i=0;i<HASHSIZE;i++) table->hashlist[i]=NULL; return table; }
hash表中的标签。就相当于在图书观的那张表中,工科类被编号1234一样。hash表中也要将key做一个标签,通过key可以快速定位table中的hashlist,进而快速提取数据。
hash算法有很多,可参考http://hi.baidu.com/hytjfxk/blog/item/46f6feceafbe622392457e0a.html
我截取其中一个比较简单的算法作为我的hash算法,它将字符串转换成了响应的整数。
unsigned long getHashValue(char *string){ unsigned long ret=0; long n; unsigned long v; int r; if(NULL == string){ return 0; } /* unsigned char b[16]; MD5(c,strlen(c),b); return(b[0]|(b[1]<<8)|(b[2]<<16)|(b[3]<<24)); */ n=0x100; while (*string) { v=n|(*string); n+=0x100; r= (int)((v>>2)^v)&0x0f; ret=(ret<<r)|(ret>>(32-r)); ret&=0xFFFFFFFFL; ret^=v*v; string++; // printf("while is over\n"); } return((ret>>16)^ret);}由于我们table的大小为HASHSIZE,所以要将key放入表中的话,得到的hash值还需整除HASHSIZE。
将标签和数据插入表中(int insertHash(void *key,void *data,hashTable_t *tab)),比如我要《电路原理》这部书放置在电子信息工程这张表里,key是电路原理,data是电路原理的内容,table是电子信息工程。 hashlist是表中一个个分类。
/*检查key是否已经存在于表中*/int UpdateHashList(void *key,void *data,struct hashEntry_s *hashlist,hashTable_t *tab){ if(hashlist !=NULL){ struct hashEntry_s *pos; for(pos=hashlist;pos != NULL;pos=pos->next){ if(strcmp(key,pos->key)==0){ pos->key = key; pos->data =data; return 0; } } } return -1;}int insertHash(void *key,void *data,hashTable_t *tab){ int index; index =getHashValue((char *)key)%HASHSIZE;// printf("index:%d\n",index); if(UpdateHashList(key,data,tab->hashlist[index],tab)<0){ struct hashEntry_s *l; l= hashEntryNew(key,data); if(tab->hashlist[index] == NULL){ tab->hashlist[index] = l; printf("insert data:%s\n",(char *)tab->hashlist[index]->data); }else{ struct hashEntry_s *pos; for(pos = tab->hashlist[index];pos->next !=NULL;pos->next){ pos= l; } } } return 0;}
得到元素数据(void *getHashData(void *key,hashTable_t *tab))。假如要取《电路原理》的信息,那么key即为电路原理,tab是电子信息工程那张表。
void *getHashData(void *key,hashTable_t *tab){int index;char *get_data;index = getHashValue((char *)key)%HASHSIZE;printf("get index :%d\n",index);struct hashEntry_s *pos;for(pos = tab->hashlist[index];pos !=NULL;pos = pos->next){if(strcmp(key,pos->key) == 0){return pos->data;}}return NULL;}
删除表信息
int removeHash(void *key,hashTable_t *tab)
{int index;index = getHashValue((char *)key)%HASHSIZE;struct hashEntry_s *pos;for(pos=tab->hashlist[index];pos != NULL;pos=pos->next,index++){if(strcmp(key,pos->key) == 0){pos->key = NULL;pos->data = NULL;if(pos->next != NULL){pos =pos->next;}else{tab->hashlist[index] =NULL;}return 0;}return -1;}printf("remove over!\n");return -1;}
按照上面的思路,假如你要从图书馆这个大表开始查的话,得建两张hash表,一张是图书馆,一张是电子信息。查的时候,图书馆表中的key是电子信息,电子信息表中的key是电路原理。
下面是把上面代码整个起来做的一个简单测试。
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <malloc.h>#define HASHSIZE 67struct hashEntry_s{void *key;void *data;struct hashEntry_s *next;};struct hashTable_s{struct hashEntry_s **hashlist;}; typedef struct hashTable_s hashTable_t;unsigned long getHashValue(char *string){ unsigned long ret=0; long n; unsigned long v; int r;if(NULL == string){return 0;} /* unsigned char b[16]; MD5(c,strlen(c),b); return(b[0]|(b[1]<<8)|(b[2]<<16)|(b[3]<<24)); */ n=0x100; while (*string) { v=n|(*string); n+=0x100; r= (int)((v>>2)^v)&0x0f; ret=(ret<<r)|(ret>>(32-r)); ret&=0xFFFFFFFFL; ret^=v*v; string++;//printf("while is over\n"); } return((ret>>16)^ret);}hashTable_t *createHashTable(void){hashTable_t *table;int i,len,primesize;table = malloc(sizeof(hashTable_t));if(NULL == table){printf("error in createtable");return NULL;}len = sizeof(struct hashEntry_s *)*HASHSIZE;table->hashlist = malloc(len);if(table->hashlist == NULL){printf("error in createtable\n");exit(1);}for(i=0;i<HASHSIZE;i++)table->hashlist[i]=NULL;return table; }inline struct hashEntry_s *hashEntryNew(void *key, void *data){ struct hashEntry_s *new = malloc(sizeof(struct hashEntry_s));memset(new,0,sizeof(struct hashEntry_s)); new->key = key; new->data = data; new->next = NULL; return new;}int UpdateHashList(void *key,void *data,struct hashEntry_s *hashlist,hashTable_t *tab){if(hashlist !=NULL){struct hashEntry_s *pos;for(pos=hashlist;pos != NULL;pos=pos->next){if(strcmp(key,pos->key)==0){pos->key = key;pos->data =data;return 0;}}}return -1;}int insertHash(void *key,void *data,hashTable_t *tab){int index;index =getHashValue((char *)key)%HASHSIZE;//printf("index:%d\n",index);if(UpdateHashList(key,data,tab->hashlist[index],tab)<0){struct hashEntry_s *l;l= hashEntryNew(key,data);if(tab->hashlist[index] == NULL){tab->hashlist[index] = l;printf("insert data:%s\n",(char *)tab->hashlist[index]->data);}else{struct hashEntry_s *pos;for(pos = tab->hashlist[index];pos->next !=NULL;pos->next){pos= l;} } }return 0;}void *getHashData(void *key,hashTable_t *tab){int index;char *get_data;index = getHashValue((char *)key)%HASHSIZE;printf("get index :%d\n",index);struct hashEntry_s *pos;for(pos = tab->hashlist[index];pos !=NULL;pos = pos->next){if(strcmp(key,pos->key) == 0){return pos->data;}}return NULL;}int removeHash(void *key,hashTable_t *tab){int index;index = getHashValue((char *)key)%HASHSIZE;struct hashEntry_s *pos;for(pos=tab->hashlist[index];pos != NULL;pos=pos->next,index++){if(strcmp(key,pos->key) == 0){pos->key = NULL;pos->data = NULL;if(pos->next != NULL){pos =pos->next;}else{tab->hashlist[index] =NULL;}return 0;}return -1;}printf("remove over!\n");return -1;}int main(void){hashTable_t *table_a;int i=0;char *data ="hello";char *getdata ="world" ;char *key ="1";table_a = createHashTable();if(table_a == NULL){printf("error!\n");return -1;}insertHash(key,data,table_a);getdata = getHashData(key,table_a);if(getdata == NULL ){printf("wo cao !!!\n"); return -1;}printf("get hash data :%s\n",getdata);char *data2="next!";insertHash(key,data2,table_a);getdata = getHashData(key,table_a);if(getdata == NULL ){printf("empty !!!\n"); return -1;}printf("get hash data :%s\n",getdata);removeHash(key,table_a);getdata = getHashData(key,table_a);if(getdata == NULL ){printf("empty !!!\n"); return -1;}printf("get data remove:%s\n",getdata);free(table_a);return 0;}
- hash表的简单说明以及例子
- 简单的hash解引用例子
- 【OC学习-28】自定义对象的归档和解归档:例子说明以及简单总结
- 关于断点续传的例子以及说明
- autotools简单例子说明
- Hash表的简单应用
- Hash 的解释说明
- dtree使用手册以及简单的例子
- dtree使用手册以及简单的例子
- dtree使用手册以及简单的例子
- hash-table基础以及一些运用例子
- window.open的例子和使用方法以及参数说明
- window.open的例子和使用方法以及参数说明
- window.open的例子和使用方法以及参数说明
- window.open的例子和使用方法以及参数说明
- window.open的例子和使用方法以及参数说明
- window.open的例子和使用方法以及参数说明
- 正则表达式使用方式以及以及简单的例子
- light oj 1257 树的直径
- 黑马程序员_学习记录03:函数的几个概念
- android ListView几个比较特别的属性
- Rose中的四种视图
- pc中的时间
- hash表的简单说明以及例子
- poj 3468 A Simple Problem with Integers
- HDU 1390 Binary Numbers
- Linux 信号signal处理机制
- Why CE-GUI sucks
- android中activity之间各种效果图转换
- 简易六字诀养生法
- 强化站内SEO做好网站基础
- ProtocolBuffer和lzo技术Hadoop系统上的使用