【发布时间】:2018-04-16 01:52:53
【问题描述】:
我已经实现了一个双哈希来存储和查找整数。要存储的项目总数约为 5k。为此,首先我 malloc 一个大小约为 10K 的数据库。要创建条目,首先我调用 find 函数。如果返回的地址值为“0”,即一个空槽,则插入项目。插入工作。但是,对于删除和修改,查找功能有时会失败。当发生以下事件序列时,就会发生这种情况。
entry1 被插入到索引 10 中。 entry2 被插入到索引 20 中。 entry3 在索引 10 处发生第一次碰撞,然后在索引 20 处发生第二次碰撞,最后 entry3 在索引 30 处插入。 然后entry2被删除。 现在查找 entry3 会返回索引 20,但这个地方没有任何价值。因此修改/删除失败。
您能否建议如何编写正确的查找函数?如果不使用“(*entry)->key != 0”检查,我无法找到终止 do-while 循环的条件。
谢谢。
#define DB_HASH_LEN 10009
typedef struct node_ {
u_int32_t key;
} hashnode_t;
int
vnid_db_open()
{
u_int32_t db_size = DB_HASH_LEN * sizeof(*db_start);
db_start = malloc(db_size);
if (db_start == NULL) {
return 0;
} else {
memset(db_start, 0, db_size);
return 1;
}
}
static inline u_int32_t
get_hash_index(u_int32_t key, u_int32_t hash_len)
{
return (key % hash_len);
}
static inline u_int32_t
get_hash_offset(u_int32_t key, u_int32_t hash_len)
{
return (1 + ((key/hash_len) % (hash_len - 1)));
}
void
find_entry(u_int32_t key, hashnode_t **entry)
{
u_int32_t index = get_hash_index(key, DB_HASH_LEN);
u_int32_t offset = get_hash_offset(key, DB_HASH_LEN);
do {
*entry = db_start + index;
index = (index + offset) % DB_HASH_LEN;
} while ((*entry)->key != 0 && (*entry)->key != key);
}
int
main(void)
{
hashnode_t *node = NULL;
u_int32_t op, key;
vnid_db_open();
while (1) {
printf("op:");
scanf("%d", &op);
getchar();
printf("key:");
scanf("%d", &key);
getchar();
switch (op) {
case(0):
find_entry(key, &node);
if (node->key == 0) {
node->key = key;
printf("inserted %d\n", key);
} else if (node->key == key) {
printf("key %d exists for insert\n", key);
} else {
printf("key %d not found for insert\n", key);
}
break;
case(1):
find_entry(key, &node);
if (node->key == key) {
node->key = 0;
printf("deleted %d\n", key);
} else {
printf("key not found %d for delete\n", key);
}
break;
case(2):
find_entry(key, &node);
if (node->key == key) {
printf("found %d\n", key);
} else {
printf("key not found %d for lookup\n", key);
}
break;
default:
break;
}
fflush(stdin);
}
return 0;
}
bash-3.2$ ./a.out
op:0
key:11111111
index 1121 offset 1111
inserted 11111111
op:0
key:11111112
index 1122 offset 1111
inserted 11111112
op:0
key:11111113
index 1123 offset 1111
inserted 11111113
op:0
key:2111113
index 9223 offset 211
inserted 2111113
op:0
key:2111114
index 9224 offset 211
inserted 2111114
op:0
key:2111114
index 9224 offset 211
key 2111114 exists for insert
op:0
key:2111115
index 9225 offset 211
inserted 2111115
op:0
key:9223
index 9223 offset 1 index 9224 offset 1 index 9225 offset 1 index 9226 offset 1
inserted 9223
op:1
key:2111113
index 9223 offset 211
deleted 2111113
op:2
key:9223
index 9223 offset 1
key not found 9223 for lookup
PS:如果哈希表中不存在条目,然后查找最终会执行一个完整的循环并且索引将匹配 start_index 并且此时我可以终止搜索,我可以引入不同的查找函数吗?请看下面的代码。
void
find_entry1(u_int32_t key, hashnode_t **entry)
{
u_int32_t index = get_hash_index(key, DB_HASH_LEN);
u_int32_t offset = get_hash_offset(key, DB_HASH_LEN);
u_int32_t start_index = index;
do {
printf("index %d offset %d ", index, offset);
*entry = db_start + index;
index = (index + offset) % DB_HASH_LEN;
} while ((start_index != index) && ((*entry)->key != key));
printf("\n");
}
学分:
【问题讨论】:
-
请把插入和删除函数也贴出来。
-
您的哈希方法称为“线性探测”。请参阅 cs.rmit.edu.au/online/blackboard/chapter/05/documents/… 以获得可以修复代码的良好描述。
-
谢谢。我已经粘贴了测试数据集。仅对于 1。因此对于较大的值,此哈希不是线性探测。