【问题标题】:Need help to write a lookup function for double hash implementation需要帮助编写双哈希实现的查找函数
【发布时间】: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");
}

学分:

how to search using double hash in c

【问题讨论】:

  • 请把插入和删除函数也贴出来。
  • 您的哈希方法称为“线性探测”。请参阅 cs.rmit.edu.au/online/blackboard/chapter/05/documents/… 以获得可以修复代码的良好描述。
  • 谢谢。我已经粘贴了测试数据集。仅对于 1。因此对于较大的值,此哈希不是线性探测。

标签: c++ c hash


【解决方案1】:

根据我在评论中提到的文章,您必须为“已删除键”保留一个特殊值,这样您的搜索就不会在找到零时终止。

所以零表示“未使用”,“特殊值”(例如 -1)表示“已删除,请继续查找”。具有“特殊价值”的条目可以重复使用。

当您返回开始搜索的“首选索引”时,您必须终止搜索。搜索时表示“未找到”,插入时表示“表已满”。

查看文章了解详情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 2019-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多