diff --git a/c-cpp/18_hash/listhash/listhash.c b/c-cpp/18_hash/listhash/listhash.c new file mode 100644 index 00000000..cf36a95d --- /dev/null +++ b/c-cpp/18_hash/listhash/listhash.c @@ -0,0 +1,350 @@ +/************************************************************************* + > File Name: listhash.c + > Author: jinshaohui + > Mail: jinshaohui789@163.com + > Time: 18-11-07 + > Desc: + ************************************************************************/ +#include +#include +#include +#include +#include"listhash.h" + + +hashtab * hashtab_create(int size,hash_key_func hash_value, + keycmp_func keycmp,hash_node_free_func hash_node_free) +{ + hashtab * h = NULL; + int i = 0; + + if ((size < 0) || (hash_value == NULL) || (keycmp == NULL)) + { + return NULL; + } + + h = (hashtab *)malloc(sizeof(hashtab)); + if (h == NULL) + { + return NULL; + } + + h->htables = (hashtab_node **)malloc(size * sizeof(hashtab_node*)); + if (h->htables == NULL) + { + return NULL; + } + + h->size = size; + h->nel = 0; + h->hash_value = hash_value; + h->keycmp = keycmp; + h->hash_node_free = hash_node_free; + + for (i = 0; i < size; i++) + { + h->htables[i] = NULL; + } + + return h; +} + +void hashtab_destory(hashtab *h) +{ + int i = 0; + hashtab_node * cur = NULL; + hashtab_node * tmp = NULL; + + if (h == NULL) + { + return; + } + + for (i = 0; i size; i++) + { + cur = h->htables[i]; + while (cur != NULL) + { + tmp = cur; + cur = cur->next; + h->hash_node_free(tmp); + } + h->htables[i] = NULL; + } + + free(h); + return; +} + +int hashtab_insert(hashtab * h,void *key,void *data) +{ + unsigned int hvalue = 0; + int i = 0; + hashtab_node *cur = NULL; + hashtab_node *prev = NULL; + hashtab_node *newnode = NULL; + + if ((h == NULL) || (key == NULL) || (data == NULL)) + { + return 1; + } + + /*获取hash 数值*/ + hvalue = h->hash_value(h,key); + cur = h->htables[hvalue]; + /*hash桶中元素是从小到大排列的,找到要插入的位置*/ + while((cur != NULL) && (h->keycmp(h,key,cur->key) > 0)) + { + prev = cur; + cur = cur->next; + } + + /*如果key和当前key比对一致,直接返回,数据已经存在*/ + if ((cur != NULL) && (h->keycmp(h,key,cur->key) == 0)) + { + return 2; + } + + newnode = (hashtab_node *)malloc(sizeof(hashtab_node)); + if (newnode == NULL) + { + return 3; + } + + newnode->key = key; + newnode->data = data; + if (prev == NULL) + { + newnode->next = h->htables[hvalue]; + h->htables[hvalue] = newnode; + } + else + { + newnode->next = prev->next; + prev->next = newnode; + } + + h->nel++; + return 0; +} + +hashtab_node *hashtab_delete(hashtab *h, void *key) +{ + int hvalue = 0; + int i = 0; + hashtab_node *cur = NULL; + hashtab_node *prev = NULL; + + if ((h == NULL) || (key == NULL)) + { + return NULL; + } + + /*获取hash 数值*/ + hvalue = h->hash_value(h,key); + cur = h->htables[hvalue]; + /*hash桶中元素是从小到大排列的,找到要插入的位置*/ + while((cur != NULL) && (h->keycmp(h,key,cur->key) >= 0)) + { + if (h->keycmp(h,key,cur->key) == 0) + { + if (prev == NULL) + { + h->htables[hvalue] = cur->next; + } + else + { + prev->next = cur->next; + } + return cur; + } + prev = cur; + cur = cur->next; + } + + return NULL; +} + +void *hashtab_search(hashtab*h,void *key) +{ + int hvalue = 0; + int i = 0; + hashtab_node *cur = NULL; + + if ((h == NULL) || (key == NULL)) + { + return NULL; + } + + /*获取hash 数值*/ + hvalue = h->hash_value(h,key); + cur = h->htables[hvalue]; + /*hash桶中元素是从小到大排列的,找到要插入的位置*/ + while((cur != NULL) && (h->keycmp(h,key,cur->key) >= 0)) + { + if (h->keycmp(h,key,cur->key) == 0) + { + return cur->data; + } + cur = cur->next; + } + + return NULL; +} + +void hashtab_dump(hashtab *h) +{ + int i = 0; + hashtab_node * cur = NULL; + + if (h == NULL) + { + return ; + } + + printf("\r\n----开始--size[%d],nel[%d]------------",h->size,h->nel); + for( i = 0; i < h->size; i ++) + { + printf("\r\n htables[%d]:",i); + cur = h->htables[i]; + while((cur != NULL)) + { + printf("key[%s],data[%s] ",cur->key,cur->data); + cur = cur->next; + } + } + + printf("\r\n----结束--size[%d],nel[%d]------------",h->size,h->nel); +} + +struct test_node +{ + char key[80]; + char data[80]; +}; + +unsigned int siample_hash(const char *str) +{ + register unsigned int hash = 0; + register unsigned int seed = 131; + + while(*str) + { + hash = hash*seed + *str++; + } + + return hash & (0x7FFFFFFF); +} + +int hashtab_hvalue(hashtab *h,const void *key) +{ + return (siample_hash(key) % h->size); +} + +int hashtab_keycmp(hashtab *h,const void *key1,const void *key2) +{ + return strcmp(key1,key2); +} + +void hashtab_node_free(hashtab_node*node) +{ + struct test_node * ptmp = NULL; + + ptmp = container(node->key,struct test_node,key); + + free(ptmp); +} + +int main () +{ + + int i = 0; + int res = 0; + char *pres = NULL; + hashtab_node * node = NULL; + struct test_node *p = NULL; + hashtab *h = NULL; + + h = hashtab_create(5,hashtab_hvalue,hashtab_keycmp,hashtab_node_free); + assert(h!= NULL); + while(1) + { + p = (struct test_node*)malloc(sizeof(struct test_node)); + assert(p != NULL); + printf("\r\n 请输入key 和value,当可以等于\"quit\"时退出"); + scanf("%s",p->key); + scanf("%s",p->data); + + if(strcmp(p->key,"quit") == 0) + { + free(p); + break; + } + + res = hashtab_insert(h,p->key,p->data); + if (res != 0) + { + printf("\r\n key[%s],data[%s] insert failed %d",p->key,p->data,res); + } + else + { + printf("\r\n key[%s],data[%s] insert success %d",p->key,p->data,res); + } + } + + hashtab_dump(h); + + while(1) + { + p = (struct test_node*)malloc(sizeof(struct test_node)); + assert(p != NULL); + printf("\r\n 请输入key 查询value的数值,当可以等于\"quit\"时退出"); + scanf("%s",p->key); + + if(strcmp(p->key,"quit") == 0) + { + free(p); + break; + } + pres = hashtab_search(h,p->key); + if (pres == NULL) + { + printf("\r\n key[%s] search data failed",p->key); + } + else + { + printf("\r\n key[%s],search data[%s] success",p->key,pres); + } + free(p); + } + hashtab_dump(h); + while(1) + { + p = (struct test_node*)malloc(sizeof(struct test_node)); + assert(p != NULL); + printf("\r\n 请输入key 删除节点的数值,当可以等于\"quit\"时退出"); + scanf("%s",p->key); + + if(strcmp(p->key,"quit") == 0) + { + free(p); + break; + } + node = hashtab_delete(h,p->key); + if (node == NULL) + { + printf("\r\n key[%s] delete node failed ",p->key); + } + else + { + printf("\r\n key[%s],delete data[%s] success",node->key,node->data); + h->hash_node_free(node); + } + free(p); + hashtab_dump(h); + } + + hashtab_destory(h); + return 0; + +} diff --git a/c-cpp/18_hash/listhash/listhash.h b/c-cpp/18_hash/listhash/listhash.h new file mode 100755 index 00000000..2e42adab --- /dev/null +++ b/c-cpp/18_hash/listhash/listhash.h @@ -0,0 +1,53 @@ +/************************************************************************* + > File Name: listhash.h + > Author: jinshaohui + > Mail: jinshaohui789@163.com + > Time: 18-11-06 + > Desc: 根据linux内核模块hashtab编写用户层hashtab接口 + linux-4.19.1\security\selinux\ss\hashtab.c + linux-4.19.1\security\selinux\ss\hashtab.h + ************************************************************************/ + + +#ifndef __HASHTAB_H__ +#define __HASHTAB_H__ + + +typedef struct _hashtab_node +{ + void * key; + void * data; + struct _hashtab_node *next; +}hashtab_node; + +typedef struct _hashtab +{ + hashtab_node **htables; /*哈希桶*/ + int size; /*哈希桶的最大数量*/ + int nel; /*哈希桶中元素的个数*/ + int (*hash_value)(struct _hashtab *h,const void *key); /*哈希函数*/ + int (*keycmp)(struct _hashtab *h,const void *key1,const void *key2);/*哈希key比较函数,当哈希数值一致时使用*/ + void (*hash_node_free)(hashtab_node *node); +}hashtab; + + +#define HASHTAB_MAX_NODES (0xffffffff) + +typedef int (*hash_key_func)(struct _hashtab *h,const void *key); /*哈希函数*/ +typedef int (*keycmp_func)(struct _hashtab *h,const void *key1,const void *key2);/*哈希key比较函数,当哈希数值一致时使用*/ +typedef void (*hash_node_free_func)(hashtab_node *node); +/*根据当前结构体元素的地址,获取到结构体首地址*/ +#define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#define container(ptr,type,member) ({\ + const typeof( ((type *)0)->member) *__mptr = (ptr);\ + (type *) ( (char *)__mptr - offsetof(type,member));}) + + +hashtab * hashtab_create(int size,hash_key_func hash_value, + keycmp_func keycmp,hash_node_free_func hash_node_free); +void hashtab_destory(hashtab *h); +int hashtab_insert(hashtab * h,void *key,void *data); +hashtab_node *hashtab_delete(hashtab *h, void *key); +void *hashtab_search(hashtab*h,void *key); + +#endif