赞
踩
近来无聊,决定动手写点程序练练手,所以从最基础的哈希表数据结构开始,全程参考的此处的GitHub项目
第一次尝试搭建极简的C语言开发环境(对于编程小白不太友好,不建议),网上教程较多,不赘述,比如这、这
哈希表
哈希冲突是不可避免的,常用的解决方法有两种开放地址法、链表法
本文基于开放地址法,开放地址法中有三种方式来寻找其他的位置,分别是**「线性探测」、「二次探测」、「再哈希法」**。本文采用线性探测法,即若插入位置已经有值,则向下顺序寻找空位置进行插入。
哈希表应该具有的API接口
构建每个元素和和哈希表的数据结构
typedef struct {
char* key;
char* value;
} ht_item;
typedef struct {
int size;
int count;
ht_item** items;
} ht_hash_table;
初始化元素:malloc申请新元素的空间,并将key和value对应赋值。
#include <stdlib.h>
#include <string.h>
static ht_item* ht_new_item(const char* k, const char* v) {
ht_item* i = malloc(sizeof(ht_item));
i->key = strdup(k);
i->value = strdup(v);
return i;
}
初始化哈希表:malloc申请哈希表的空间,calloc申请存放元素地址的空间(与malloc不同的是申请的区域为初始化为0),并将size和count对应赋值。
ht_hash_table* new_ht() {
ht_hash_table* h = malloc(sizeof(ht_hash_table)) ;
h->size = 53;
h->count = 0;
h->items = calloc((size_t)h->size, sizeof(ht_item*))
return h;
}
删除:释放掉申请的内存,防止内存泄漏。注意释放的先后顺序,i和h最后才释放
static void ht_del_item(ht_item* i) {
free(i->key);
free(i->value);
free(i);
}
void ht_del_hash_table(ht_hash_table* h)
{
for(int i = 0;i <h->size;i++)
{
if(h->items[i] != NULL)
ht_delete_item(h->items[i]);
}
free(h->items);
free(h);
}
使用static关键字修饰的静态函数不能被其它文件调用,作用于仅限于本文件
程序其中用到的基础C语言的库函数:
头文件:#include <stdlib.h>
定义函数:void* malloc (size_t size);
参数说明:size 为需要分配的内存空间的大小,以字节(Byte)计。
函数说明:malloc() 在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。如果希望在分配内存的同时进行初始化,请使用 calloc() 函数。
返回值:分配成功返回指向该内存的地址,失败则返回 NULL
头文件:#include <string.h>
定义函数:char * strdup(const char *s);
函数说明:strdup()会先用maolloc()配置与参数s 字符串相同的空间大小,然后将参数s 字符串的内容复制到该内存地址,然后把该地址返回。该地址最后可以利用free()来释放。
返回值:返回一字符串指针,该指针指向复制后的新字符串地址。若返回NULL 表示内存不足。
定义函数:void* calloc (size_t num, size_t size);
函数说明:calloc() 在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0。所以它的结果是分配了 num*size 个字节长度的内存空间,并且每个字节的值都是0。
返回值:分配成功返回指向该内存的地址,失败则返回 NULL。
我们将使用一个通用字符串哈希函数
此哈希函数有两个步骤:
static int ht_hash(const char* s, const int a, const int m)
{
long hash = 0;
const int len_s = strlen(s);
for (int i = 0; i < len_s; i++) {
hash += (long)pow(a, len_s - (i+1)) * s[i];
hash = hash % m;
}
return (int)hash;
}
int insert(ht_hash_table* h, const char* k, const char* v) { ht_item* i = ht_new_item(k,v); int index = ht_hash(k,151,53); if(h->count >= h->size) return -1; h->count++; while(1) { if((h->items[index])==NULL) { h->items[index] = i; return index; } index++; if(index == h->size) index = 0; } } char* search(ht_hash_table* h, const char* k) { int index = ht_hash(k,151,53); for (int i = 0; i < h->size;i++) { if(h->items[index]!=NULL) if(strcmp(h->items[index]->key,k)==0) return h->items[index]->value; index++; if(index == h->size) index = 0; } return NULL; } void delete(ht_hash_table* h, const char* k) { int index = ht_hash(k,151,53); for (int i = 0; i < h->size;i++) { if(h->items[index]!=NULL) if(strcmp(h->items[index]->key,k) == 0) { ht_del_item(h->items[index]); h->items[index] = NULL; h->count--; return ; } index++; if(index == h->size) index = 0; } return ; }
int main(void) { ht_hash_table* ht=new_ht(); insert(ht,"niuniu","hahaha"); insert(ht,"shuoshuo","xixixi"); char* s = search(ht,"shuoshuo"); if(s==NULL) printf("查找失败 %d\n",s); else printf(s); delete(ht,"shuoshuo"); char* c = search(ht,"shuoshuo"); if(c==NULL) printf("查找失败 %d\n",c); else printf(c); ht_del_hash_table(ht); return 0; }
未完待续。。。
#include <stdlib.h> #include <string.h> #include "hash_table.h" void ht_delete_item(ht_hash_table* h){} static ht_item* ht_new_item(const char* k, const char* v) { ht_item* i = malloc(sizeof(ht_item)); i->key = strdup(k); i->value = strdup(v); return i; } static void ht_del_item(ht_item* i) { free(i->key); free(i->value); free(i); } ht_hash_table* new_ht() { ht_hash_table* h = malloc(sizeof(ht_hash_table)) ; h->size = 53; h->count = 0; h->items = calloc((size_t)h->size, sizeof(ht_item*)); return h; } void ht_del_hash_table(ht_hash_table* h) { for(int i = 0;i <h->size;i++) { if(h->items[i] != NULL) ht_delete_item(h->items[i]); } free(h->items); free(h); } static int ht_hash(const char* s, const int a, const int m) { long hash = 0; const int len_s = strlen(s); for (int i = 0; i < len_s; i++) { hash += (long)pow(a, len_s - (i+1)) * s[i]; hash = hash % m; } return (int)hash; } int insert(ht_hash_table* h, const char* k, const char* v) { ht_item* i = ht_new_item(k,v); int index = ht_hash(k,151,53); if(h->count >= h->size) return -1; h->count++; while(1) { if((h->items[index])==NULL) { h->items[index] = i; return index; } index++; if(index == h->size) index = 0; } } char* search(ht_hash_table* h, const char* k) { int index = ht_hash(k,151,53); for (int i = 0; i < h->size;i++) { if(h->items[index]!=NULL) if(strcmp(h->items[index]->key,k)==0) return h->items[index]->value; index++; if(index == h->size) index = 0; } return NULL; } void delete(ht_hash_table* h, const char* k) { int index = ht_hash(k,151,53); for (int i = 0; i < h->size;i++) { if(h->items[index]!=NULL) if(strcmp(h->items[index]->key,k) == 0) { ht_del_item(h->items[index]); h->items[index] = NULL; h->count--; return ; } index++; if(index == h->size) index = 0; } return ; } int main(void) { ht_hash_table* ht=new_ht(); insert(ht,"niuniu","hahaha"); insert(ht,"shuoshuo","xixixi"); char* s = search(ht,"shuoshuo"); if(s==NULL) printf("查找失败 %d\n",s); else printf(s); delete(ht,"shuoshuo"); char* c = search(ht,"shuoshuo"); if(c==NULL) printf("查找失败 %d\n",c); else printf(c); ht_del_hash_table(ht); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。