开散列(也称为拉链法),也是解决哈希冲突的一类方法。
应用场景:
当插入数值时,如遇到利用哈希函数对关键字进行分析时得到相同的哈希地址的情况,就需要相应的解决方法使具有相同哈希地址的不同关键字在允许插入的前提下都可以得到插入操作。拉链法就是将哈希地址的内容改为一个指针,将具有相同哈希地址的不同关键字串联起来。
结构体:
对于该哈希表应该具有存储空间、存储大小和处理关键字的哈希函数;对于结点应该具有关键字、相应值和下一结点的指向。
代码:
typedef struct HashElem { KeyType key; ValType value; struct HashElem* next; } HashElem; // 数组的每一个元素是一个不带头结点的链表 // 对于空链表, 我们使用 NULL 来表示 typedef struct HashTable { HashElem* data[HashMaxSize]; size_t size; HashFunc func; } HashTable;
哈希初始化:
1.首先对输入参数进行非法性判断;
2.对结构体进行初始化;
a)哈希函数的初始化;
b)哈希表中一存储数量;
c)哈希表中的元素指向。
代码:
void HashInit(HashTable* ht, HashFunc hash_func){ if(ht == NULL){ return; } ht->func = hash_func; ht->size = 0; int i = 0; for(;i<HashMaxSize;++i){ ht->data[i] = NULL; } return; }
哈希插入:
1..判断传入参数的非法性;
2.判断哈希表是否已满;
3.调用哈希函数 ,对插入项的关键字进行处理,得到哈希地址,进行检测
a)存在,直接返回;
b)不存在,找到xiang'y
代码:
void HashInsert(HashTable* ht, KeyType key, ValType value){ if(ht ==NULL){ //非法输入 return; } if(ht->size > 0.8*HashMaxSize){ //哈希表已“满” return; } int offset = ht->func(key); HashElem* new = CreateNode(key,value); while(1){ if(ht->data[offset] ==NULL){ ht->data[offset] = new; ++ht->size; return; }else{ HashElem* cur = ht->data[offset]; while(cur->next != NULL){ if(cur->key == key){ free(new); return; } cur = cur->next; } cur->next = new; ++ht->size; return; } } return; }
哈希删除:
代码:
void HashRemove(HashTable* ht, KeyType key){ if(ht ==NULL){ //非法输入 return; } if(ht->size == 0){ //哈希表为空 return; } int offset = ht->func(key); int i = 0; for(;i<HashMaxSize;++i){ if(ht->data[offset] != NULL){ HashElem* cur = ht->data[offset]; HashElem* parent = NULL; for(;cur!=NULL;cur= cur->next){ if(cur->key == key){ if(parent == NULL){ free(cur); --ht->size; ht->data[i] = NULL; return; }else{ parent->next = cur->next; free(cur); --ht->size; return; } } parent = cur; } } }//循环结束 return; }
哈希查找:
代码:
int HashFind(HashTable* ht, KeyType key, ValType* value){ if(ht == NULL){ //非法输入 return 0; } if(ht->size == 0){ //哈希表为空 return 0; } int i = 0; for(;i<HashMaxSize;++i){ if(ht->data[i] != NULL){ HashElem* cur = ht->data[i]; for(;cur!= NULL;cur = cur->next){ if(cur->key == key){ *value = cur->value; return 1; } } }//判断是否为空 }//循环结束 return 0; }
哈希销毁:
代码:
void HashDestroy(HashTable* ht){ if(ht == NULL){ //非法输入 return; } if(ht->size == 0){ return; } int i = 0; for(;i<HashMaxSize;++i){ if(ht->data[i]!= NULL){ HashElem* cur = ht->data[i]; HashElem* tmp = NULL; while(cur->next != NULL){ HashElem* tmp = cur; cur= cur->next; free(tmp); --ht->size; } tmp = cur; cur = NULL; free(tmp); --ht->size; } }//循环结束 return; }