链式哈希表

将数据存储在桶中-桶是链表。如果冲突,增大链表长度

需要用到我的链表

头文件

//
//  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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值