头文件
//
// ohash.h
// ohash
//
// Created by bikang on 16/9/23.
// Copyright (c) 2016年 bikang. All rights reserved.
//
#ifndef __ohash__ohash__
#define __ohash__ohash__
#include <stdlib.h>
typedef struct OHTbl_{
int positions;//数据个数
void *vacated;//哨兵--指向不可用的元素
int (*h1)(const void *key);//哈希函数
int (*h2)(const void *key);//哈希函数
int (*match)(const void *key1,const void *key2);//比较,匹配
void (*destroy)(void *data);//内存释放函数
int size;//数据的多少
void **table;//数据
}OHTbl;
int ohtbl_init(OHTbl *htbl,int positions,int (*h1)(const void *key),int (*h2)(const void *key),
int(*match)(const void *k1,const void *k2),
void(*destroy)(void*data));
//销毁
void ohtbl_destroy(OHTbl *htbl);
//插入
int ohtbl_insert(OHTbl *htbl,const void *data);
//删除
int ohtbl_remove(OHTbl *htbl,void **data);
//查找
int ohtbl_lookup(OHTbl *htbl,void **data);
#define ohtbl_size(htbl) ((htbl)->size)
#endif /* defined(__ohash__ohash__) */
实现代码
//
// ohash.c
// ohash
//
// Created by bikang on 16/9/23.
// Copyright (c) 2016年 bikang. All rights reserved.
//
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "ohash.h"
static char vacated;
int ohtbl_init(OHTbl *htbl,int positions,int (*h1)(const void *key),int (*h2)(const void *key),
int(*match)(const void *k1,const void *k2),
void(*destroy)(void*data)){
int i;
if((htbl->table = (void**)malloc(positions*sizeof(void*))) == NULL) return -1;
htbl->positions = positions;
for (i=0; i<htbl->positions; i++) {
htbl->table[i] = NULL;
}
htbl->vacated = &vacated;
htbl->h1 = h1;
htbl->h2 = h2;
htbl->match = match;
htbl->destroy = destroy;
htbl->size = 0;
return 0;
}
//销毁
void ohtbl_destroy(OHTbl *htbl){
int i ;
if(htbl->destroy != NULL){
for (i = 0;i< htbl->positions ; i++) {
if(htbl->table[i] != NULL && htbl->vacated != htbl->table[i])htbl->destroy(htbl->table[i]);
}
}
free(htbl->table);
memset(htbl, 0, sizeof(OHTbl));
return;
}
//插入,
int ohtbl_insert(OHTbl *htbl,const void *data){
void *temp;
int position,i;
if(htbl->size == htbl->positions) return -1;
temp = (void*) data;
if(ohtbl_lookup(htbl, &temp) == 0) return 1;
for(i = 0;i<htbl->positions;i++){
position = (htbl->h1(data)+(i*htbl->h2(data)))%htbl->positions;
if(htbl->table[position] == NULL || htbl->table[position] == htbl->vacated){
//puts("add");
htbl->table[position] = (void*)data;
//printf("htbl->table[%d]=%s\n",position,data);
htbl->size++;
return 0;
}
}
return -1;
}
//删除
int ohtbl_remove(OHTbl *htbl,void **data){
int position,i;
for(i = 0;i<htbl->positions;i++){
position = (htbl->h1(*data)+(i*htbl->h2(*data)))%htbl->positions;
if(htbl->table[position] == NULL){
return 0;
}else if(htbl->table[position] == htbl->vacated){
continue;
}else if(htbl->match(htbl->table[position],*data) == 0){
*data = htbl->table[position];
htbl->table[position] = htbl->vacated;
htbl->size--;
return 0;
}
}
return 0;
}
//查找
int ohtbl_lookup(OHTbl *htbl,void **data){
int position,i;
for(i = 0;i<htbl->positions;i++){
position = (htbl->h1(*data)+(i*htbl->h2(*data)))%htbl->positions;
//printf("positions=%d, ",position);
if(htbl->table[position] == NULL){
return -1;
}else if(htbl->match((char*)htbl->table[position],*data) == 0){
*data = htbl->table[position];
return 0;
}
}
return -1;
}
测试代码
//
// main.c
// ohash
//
// Created by bikang on 16/9/23.
// Copyright (c) 2016年 bikang. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ohash.h"
#define PRIME_TBLSIZ 1024
int match_chars(const void *k1,const void *k2){
if(strcmp((char*)k1,(char*)k2) == 0){
return 0;
}else{
return -1;
}
}
unsigned int hashpjw(const void *key){
unsigned int val = 0;
const char *ptr;
ptr = (char*) key;
while (*ptr != '\0') {
unsigned int tmp;
val = (val << 4) + (*ptr);
if(tmp = (val & 0xf0000000)){
val = val ^ (tmp >> 24);
val = val ^ tmp;
}
ptr++;
}
return val%PRIME_TBLSIZ;
}
int h1(const void*key){
unsigned int key1 = hashpjw(key);
return key1%4096;
}
int h2(const void*key){
unsigned int key1 =hashpjw(key)%4096;
if(key1 %2 == 0){
return key1+1;
}
return key1;
}
void print_table(OHTbl *t){
int i;
for(i = 0; i< t->positions;i++){
printf("t->positions[%d]=%s\n",i,t->table[i]);
}
return;
}
// m 必须 是 2 次幂, 让 h2 返回 一个 奇 数值
int main(int argc, const char * argv[]) {
int findret;
OHTbl *t1 = (OHTbl *)malloc(sizeof(OHTbl));
//初始化
ohtbl_init(t1, 64, h1, h2, match_chars, NULL);
//插入几个数据
char *s1 = "hello";
char *s2 = "hello world";
char *s3 = "struct";
char *s4 = "cpp";
ohtbl_insert(t1, s1);
ohtbl_insert(t1, s2);
ohtbl_insert(t1, s3);
ohtbl_insert(t1, s4);
printf("chtbl_size=%d\n",ohtbl_size(t1));
//删除一个数据
//print_table(t1);
//return 1;
//查找数据
findret = ohtbl_lookup(t1,(void**)&s4);
if(findret == 0){
puts("find ok\n");
}else{
puts("find faild\n");
}
//return 1;
char str_test[4] = "cpp";
char *ptr = str_test;
char **pptr = &ptr;
findret = ohtbl_remove(t1, (void**)pptr);
if(findret==0){
puts("delete sucess");
}else{
puts("delete faild");
}
//查找数据
pptr = &ptr;
findret = ohtbl_lookup(t1,(void**)pptr);
if(findret == 0){
puts("find ok\n");
}else{
puts("find faild\n");
}
printf("chtbl_size=%d",ohtbl_size(t1));
//销毁数据
ohtbl_destroy(t1);
return 0;
}