MD5:
- 不管字符串多大,生成的MD5长度都是16或32位。
- 几乎不可逆
- 字符串改变,MD5变化很大
typedef enum{
Empty;//空状态
Valid;//有效状态
Deleted //被删除的状态
} Stat;
//哈希表存储的是 键值对
typedef int KeyType;
typedef int CalType;
typedef size_t (*HashFunc) (KeyType key);
//这个结构体表示哈希表中的一个元素
typedef struct HashElem{
KeyType key;
CalType value;
Stat stat;
} HashElem;
//[0,size)这个区间不表示哈希表中有效元素的区间
typedef struct HashTable{
HashElem data[HashNaxSize];
size_t size;
HashFunc func; //函数指针指向哈希函数
} HashTable;
void HshInit(HashTable* ht. HashFuncc hash_func);
void HashDestroy(hashTable* ht);
void HashInsert(HashTable* ht, KeyType key, ValType value);
int HashFind(HashTAble* ht, KeyType key, ValType* value);
void HashDelete(HashTAble* ht, KeyType key);
size等于0 表示哈希表无效。
void hash_func(KeyType key){
offset = key%HashMaxSize;
}
void HshInit(HashTable* ht. HashFuncc hash_func){
ht->size = 0;
ht->func = hash_func;
size_t i;
for(;i < HashMaxSize; ++i)
ht->data[i].stat = Empty;
return;
}
}
void Destroy(HashTable* ht. HashFuncc hash_func){
ht->size = 0;
ht->func = NULL;
size_t i;
for(;i < HashMaxSize; ++i)
ht->data[i].stat = Empty;
return;
}
}
void HashInsert(HashTable* ht, KeyType key, ValType value){
if( ht == NULL){
//非法输入
return;
}
//1.判断hash表是否能继续插入(根据负载因子)
//假设我们此时将负载因子定义为0.8,负载因子小,效率高
if(ht->szie >= 0.8*HashMaxSize){
//发现当前hash已经达到负载因子上线
//此处直接插入失败
return;
}
//2.根据key计算 offset
size_t offset = ht->func(key);
//3.从offset线性往后查找,找到第一个状态为Empty的元素来插入
while(1){
//1.插入成功
//2.插入失败
//3.其他情况(需要进行线性探测)
if(ht->data[offset].stat != Valid){
ht->data[offset].stat = Valid;
ht->data[offset].key = key;
ht->data[offset].value = calue;
++ht->size;
return;
}else if(ht->data[offset].stat == Valid && ht->data[offset].key = key){
//如果此时发现了key值相同的元素,此时认为插入失败
//hash表中存在一个与 key 相同的元素
//此时单纯的认为插入失败
//如果要修改value的值,放开下面的函数
//TODO
return;
}else{
++offset;
if(offset >= HashMaxSize){
offset = 0;
}
} //end while(1)
}
}
int HashFind(HashTAble* ht, KeyType key, ValType* value){
if(ht == NULL || value == NULL){
//非法输入
return;
}
if(ht->size == 0){
return;
}
//1.根据key计算出offset
size_t offset = ht->func(key);
//2.从offset开始往后查找,每次取到一个元素使用key进行比较
while(1){
if(ht->data[offset].key == key && ht->data[offset].stat == stat){
//a)如果找到了key相同的元素,此时直接把value返回回去进行,查找成功
value = ht->data[offset].value;
return 1;
}else if(ht->data[offsete].stat = Empty){
//b)查到空,查找失败
return;
}else{
++offset;
//缺!!!
//c)如果与key不相同,继续向后查找
}
}
return 0;
}
void HashDelete(HashTAble* ht, KeyType key){
// 1.根据key计算户offset
if(ht == NULL){
return;
}
if(ht->size == 0){
return;
}
// 2.从offset开始一次判定当前元素的key和删除元素的key是否相等
size_t offset = ht->func(key);
while(1){
// a)如果当前的key就是要删除的key,删除当前元素即可,删除元素引入新的状态标记Deleted
if(ht->data[offset].key == key && ht->data[offset].stat == Vaild){
//找到了要删除的元素,我们需要标记成Deleted
ht->data[offset].stat = Deleted;
--ht->size;
return;
}else if(ht->data[offset].stat == Empty){
// b)如果当前的元素为空元素,key在hash表中没找到,删除失败
return;
}else{
// c)剩下的情况 ————offset,线性探测尝试查找下一个元素
++offset;
}
}
}