我在C中为学校项目实现哈希表。我选择使用链接列表单独链接。由于我显然在考虑哈希冲突,因此我无法查看如何检查是否使用了特定密钥。
下面,我到目前为止。显然,它是不完整的(例如,不能删除键值对,不重组桶以考虑插入时的最大负载因子等)。需要注意的是,我知道其他问题,但我无法弄清楚如何在不将密钥存储在某处的情况下检查是否使用了密钥。
#ifndef HASH_MAP_H
#define HASH_MAP_H
#include <stdint.h>
struct hash_map
{
uintmax_t _cardinality;
struct array_list * _buckets;
double _max_load_factor;
uintmax_t (* _hash_function)(void * value);
bool (* _equality_function)(void * value1, void * value2);
};
void hash_map_set_value_for_key(struct hash_map * const map, void * const key, void * const value);
struct hash_map * hash_map_init(uintmax_t (* hash_function)(void * value), bool (* equality_function)(void * value1, void * value2));
void hash_map_destroy(struct hash_map * const map);
uintmax_t hash_map_get_cardinality(struct hash_map const * const map);
double hash_map_get_load_factor(struct hash_map const * const map);
double hash_map_get_max_load_factor(struct hash_map const * const map);
#endif //HASH_MAP_H
#include <stdlib.h>
#include "hash_map.h"
#include "array_list.h"
#include "singly_linked_list.h"
void hash_map_set_value_for_key(
struct hash_map * const map,
void * const key,
void * const value
)
{
uintmax_t hash = map->_hash_function(key);
struct singly_linked_list * const bucket = array_list_get_value_at_index(
map->_buckets,
hash % array_list_get_cardinality(map->_buckets)
);
struct singly_linked_list_node * node = singly_linked_list_get_head(bucket);
while (node != NULL)
{
if (map->_equality_function(value, singly_linked_list_node_get_value(node)))
{
return;
}
node = singly_linked_list_node_get_next_node(node);
}
singly_linked_list_append(bucket, value);
++map->_cardinality;
}
void hash_map_destroy(
struct hash_map * const map
)
{
for (uintmax_t i = 0; i < map->_buckets->_cardinality; ++i)
{
singly_linked_list_destroy(array_list_get_value_at_index(map->_buckets, i));
}
array_list_destroy(map->_buckets);
free(map);
}
uintmax_t hash_map_get_cardinality(
struct hash_map const * const map
)
{
return map->_cardinality;
}
double hash_map_get_load_factor(
struct hash_map const * const map
)
{
return (double) map->_cardinality / array_list_get_cardinality(map->_buckets);
}
double hash_map_get_max_load_factor(
struct hash_map const * const map
)
{
return map->_max_load_factor;
}
struct hash_map * hash_map_init(
uintmax_t (* hash_function)(void *),
bool (* equality_function)(void *, void *)
)
{
struct hash_map * const map = malloc(sizeof(struct hash_map));
map->_cardinality = 0;
map->_max_load_factor = 0.7;
map->_hash_function = hash_function;
map->_equality_function = equality_function;
map->_buckets = array_list_init();
array_list_append(map->_buckets, singly_linked_list_init());
return map;
};