1. 程式人生 > >散列表(三):衝突處理的方法之開地址法(線性探測再雜湊的實現)

散列表(三):衝突處理的方法之開地址法(線性探測再雜湊的實現)

    printf("The hash table has free.\n");
}

void *hash_lookup_entry(hash_t *hash, void *key, unsigned int key_size)
{
    hash_node_t *node = hash_get_node_by_key(hash, key, key_size);
    if (node == NULL)
    {
        return NULL;
    }

    return node->value;
}

void hash_add_entry(hash_t *hash, void *key, unsigned
 int key_size,
                    void *value, unsigned int value_size)
{
    if (hash_lookup_entry(hash, key, key_size))
    {
        fprintf(stderr, "duplicate hash key\n");
        return;
    }

    unsigned int bucket = hash_get_bucket(hash, key);
    unsigned int i = bucket;
    // 找到的位置已經有人存活,向下探測
    while (hash->nodes[i].status == ACTIVE)
    {
        i = (i + 1) % hash->buckets;
        if (i == bucket)
        {
            // 沒找到,並且表滿
            return;
        }
    }

    hash->nodes[i].status = ACTIVE;
    if (hash->nodes[i].key) //釋放原來被邏輯刪除的項的記憶體
    {
        free(hash->nodes[i].key);
    }
    hash->nodes[i].key = malloc(key_size);
    memcpy(hash->nodes[i].key, key, key_size);
    if
 (hash->nodes[i].value) //釋放原來被邏輯刪除的項的記憶體
    {
        free(hash->nodes[i].value);
    }
    hash->nodes[i].value = malloc(value_size);
    memcpy(hash->nodes[i].value, value, value_size);

}

void hash_free_entry(hash_t *hash, void *key, unsigned int key_size)
{
    hash_node_t *node = hash_get_node_by_key(hash, key, key_size);
    if (node == NULL)
        return;

    // 邏輯刪除,置標誌位
    node->status = DELETED;
}

unsigned int hash_get_bucket(hash_t *hash, void *key)
{
    // 返回雜湊地址
    unsigned int bucket = hash->hash_func(hash->buckets, key);
    if (bucket >= hash->buckets)
    {
        fprintf(stderr, "bad bucket lookup\n");
        exit(EXIT_FAILURE);
    }

    return bucket;
}

hash_node_t *hash_get_node_by_key(hash_t *hash, void *key, unsigned int key_size)
{
    unsigned int bucket = hash_get_bucket(hash, key);
    unsigned int i = bucket;
    while (hash->nodes[i].status != EMPTY && memcmp(key, hash->nodes[i].key, key_size) != 0)
    {
        i = (i + 1) % hash->buckets;
        if (i == bucket)        // 探測了一圈
        {
            // 沒找到,並且表滿
            return NULL;
        }
    }
    // 比對正確,還得確認是否還存活
    if (hash->nodes[i].status == ACTIVE)
    {
        return &(hash->nodes[i]);
    }

    // 如果執行到這裡,說明i為空位或已被刪除

    return NULL;
}