将数据存储在桶中-桶是链表。如果冲突,增大链表长度
需要用到我的链表
头文件
//
// cntbl.h
// hash
//
// Created by bikang on 16/9/22.
// Copyright (c) 2016年 bikang. All rights reserved.
//
#ifndef __hash__cntbl__
#define __hash__cntbl__
#include "list.h"
#include <stdlib.h>
typedef struct CHTbl_{
int buckets;//桶的大小
unsigned int (*h)(const void *key);//哈希函数
int (*match)(const void *key1,const void *key2);//比较,匹配
void (*destroy)(void *data);//内存释放函数
int size;//数据的多少
List *table;
}CHTbl;
//初始化
int chtbl_init(CHTbl *htbl,int buckets,int (*h)(const void *key),
int(*match)(const void *k1,const void *k2),
void(*destroy)(void*data));
//销毁
void chtbl_destroy(CHTbl *htbl);
//插入
int chtbl_insert(CHTbl *htbl,void *data);
//删除
int chtbl_remove(CHTbl *htbl,void **data);
//查找
int chtbl_lookup(CHTbl *htbl,void **data);
//数据的多少
#define chtbl_size(htbl) ((htbl)->size)
#endif /* defined(__hash__cntbl__) */
实现
//
// cntbl.c
// hash
//
// Created by bikang on 16/9/22.
// Copyright (c) 2016年 bikang. All rights reserved.
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cntbl.h"
#include "list.h"
//初始化
int chtbl_init(CHTbl *htbl,int buckets,int (*h)(const void *key),
int(*match)(const void *k1,const void *k2),
void(*destroy)(void*data)){
int i;
//初始化数据
if((htbl->table =(List*)malloc(sizeof(List)*buckets) ) == NULL) return -1;
htbl->buckets = buckets;
for(i=0;i<htbl->buckets;i++){
list_init(&htbl->table[i], destroy);
}
htbl->h = h;
htbl->match = match;
htbl->destroy = destroy;
htbl->size = 0;
return 0;
}
//释放数据
void chtbl_destroy(CHTbl *htbl){
int i;
for(i=0;i<htbl->buckets;i++){
list_destroy(&htbl->table[i]);
}
free(htbl->table);
memset(htbl, 0, sizeof(CHTbl));
return;
}
//插入
int chtbl_insert(CHTbl *htbl,void *data){
void *temp;
int bucket,retval;
temp = (void*)data;
//是否存在,存在直接返回
if(chtbl_lookup(htbl, &temp) == 0) return 1;
//找到hash key,我们采用除以余数的方法
bucket = htbl->h(data)%(htbl->buckets);
//插入数据
if((retval= list_ins_next(&htbl->table[bucket], NULL, data)) == 0)htbl->size++;
return 0;
}
//删除
int chtbl_remove(CHTbl *htbl,void **data){
ListElmt *element=NULL,*prev=NULL;
int bucket=0;
bucket = htbl->h(*data)%htbl->buckets;
for(element=list_head(&htbl->table[bucket]);element!= NULL;element=list_next(element)){
if (htbl->match(*data,list_data(element)) == 0) {
//如果pre为空删除表头,否则删除pre的下一个元素
if(list_rem_next(&htbl->table[bucket], prev, data)==0){
htbl->size--;
return 0;
}else{
return -1;
}
}
prev = element;
}
return -1;
}
//查找是否存在元素
int chtbl_lookup(CHTbl *htbl,void **data){
ListElmt *element=NULL;
int bucket=0;
//printf("h->data=%d",htbl->h(*data));
//printf("data=%s",**(char**)data);
bucket = htbl->h(*data)%htbl->buckets;
for(element=list_head(&htbl->table[bucket]);element!= NULL;element=list_next(element)){
if (htbl->match(*data,list_data(element)) == 0) {
*data = list_data(element);
return 0;
}
}
return -1;
}
hash函数头文件及其实现
//
// hashpjw.h
// hash
//
// Created by bikang on 16/9/22.
// Copyright (c) 2016年 bikang. All rights reserved.
//
#ifndef __hash__hashpjw__
#define __hash__hashpjw__
#define PRIME_TBLSIZ 4096
unsigned int hashpjw(const void *key);
#endif /* defined(__hash__hashpjw__) */
//
// hashpjw.c
// hash
//
// Created by bikang on 16/9/22.
// Copyright (c) 2016年 bikang. All rights reserved.
//
#include "hashpjw.h"
unsigned int hashpjw(const void *key){
unsigned int val = 0;
const char *ptr;
ptr = (char*) key;
while (*ptr != '\0') {
unsigned int tmp;
//往左移动4位,乘以16
val = (val << 4) + (*ptr);
//printf("*ptr=%d,val=%d,",*ptr,val);
//当val大于2^28位的时候,取前四位
if(tmp = (val & 0xf0000000)){
//printf("tmp=%d,",tmp);
//val和val的前16位异或运算
val = val ^ (tmp >> 24);
//val和val的28位异或运算
val = val ^ tmp;
}
//printf("new_val=%d,",val);printf("\n");
ptr++;
}
return val%PRIME_TBLSIZ;
}
匹配函数及其头文件
//
// match.h
// hash
//
// Created by bikang on 16/9/22.
// Copyright (c) 2016年 bikang. All rights reserved.
//
#ifndef __hash__match__
#define __hash__match__
#include <stdio.h>
int match_int(const void *k1,const void *k2);
int match_chars(const void *k1,const void *k2);
#endif /* defined(__hash__match__) */
//
// match.c
// hash
//
// Created by bikang on 16/9/22.
// Copyright (c) 2016年 bikang. All rights reserved.
//
#include "match.h"
#include <string.h>
int match_int(const void *k1,const void *k2){
if(*(int*)k1 == *(int*)k2) {
return 0;
}else{
return -1;
}
}
int match_chars(const void *k1,const void *k2){
if(strcmp((char*)k1,(char*)k2) == 0){
return 0;
}else{
return -1;
}
}
测试代码
//
// main.c
// hash
//
// Created by bikang on 16/9/22.
// Copyright (c) 2016年 bikang. All rights reserved.
//
#include <stdio.h>
#include "hashpjw.h"
#include "match.h"
#include "cntbl.h"
void thashpjw();
void tres();
void tcntble();
int main(int argc, const char * argv[]) {
printf("start\n");
//测试hash函数
thashpjw();
//tres();
tcntble();
return 0;
}
void tcntble(){
void **data;
int findret;
//新建一个hash表
CHTbl *t1 = malloc(sizeof(CHTbl));
chtbl_init(t1, 1024, hashpjw, match_chars, NULL);
//插入几个数据
chtbl_insert(t1, "hello");
chtbl_insert(t1, "hello world");
chtbl_insert(t1, "struct");
chtbl_insert(t1, "cpp");
//删除一个数据
char str_test[4] = "cpp";
char *ptr = str_test;
char **pptr = &ptr;
//查找数据
findret = chtbl_lookup(t1,(void**)pptr);
if(findret == 0){
puts("find ok\n");
}else{
puts("find faild\n");
}
findret = chtbl_remove(t1, (void**)pptr);
if(findret==0){
puts("delete sucess");
}else{
puts("delete faild");
}
//查找数据
pptr = &ptr;
findret = chtbl_lookup(t1,(void**)pptr);
if(findret == 0){
puts("find ok\n");
}else{
puts("find faild\n");
}
printf("chtbl_size=%d",chtbl_size(t1));
//销毁数据
chtbl_destroy(t1);
}
void tres(){
unsigned int res = 0;
printf("res=%d,",(res << 4)& 0xf0000000);
printf("\n");
}
void thashpjw(){
unsigned int res;
res = hashpjw("adfasdd课啊");
char str_test[4] = "cpp";
char *ptr = str_test;
res = hashpjw(ptr);
printf("adfasdd convert to res=%d\n",res);
}