使用realloc

时间:2015-10-29 01:48:04

标签: c hash

我正在开发一个项目,我们将使用给定的头文件编写哈希表。到目前为止一切正常(我得到了错误,但我至少可以修复),但我遇到了一个问题。我不知道如何重新打开一个开放的寻址哈希表。我将提供我的结构,我的创建函数和我的put函数。

/// The "buckets" in the table
typedef struct Entry_t {
void* key;     ///< key must be "hashable"
void* value;   ///< value can be any type
} Entry;

/// The hash table
typedef struct Table_t {
    Entry** table;    ///< table of Entry pointers
    size_t size;      ///< number of entries in table
    size_t capacity;  ///< total capacity of table
    long (*hash)(void* key);  ///< hash function for key
    bool (*equals)(void *key1, void* key2); ///< equals function for key comparison
    void (*print)(void *key, void* value);  ///< print function for table dump debug
    size_t collisions;      ///< number of collisions throughout life of hash table
    size_t rehashes;        ///< number of rehashes throughout life of hash table
} Table;

Table* create(long (*hash)(void* key), bool (*equals)(void* key1, void* key2), 
void (*print)(void* key1, void* key2))
{
    Table* t = (Table*)malloc(sizeof(Table));
    if (t == NULL)
    {
        return NULL;
    }
    t->size = 0;
    t->capacity = INITIAL_CAPACITY;
    t->collisions = 0;
    t->rehashes = 0;
    t->table = (Entry**)calloc(t->capacity, sizeof(Entry*));
    t->hash = hash;
    t->equals = equals;
    t->print = print;
    return t;
}

我编写代码的方式,t-&gt; table [index]为null,所以在插入值之前我必须使用malloc空间。这是我的put函数。

void* put(Table* t, void* key, void* value)  // Rehashing needs to be completed
{
        int index = t->hash(key) % t->capacity;
        void* old_value = NULL;
        int check = 0;
        if (t->table[index] != NULL)
        {
                while (check == 0)
                {
                        if (t->table[index] != NULL)
                        {
                                if (t->equals(t->table[index]->key, key) == 0)
                                {
                                        index = (index + 1) % t->capacity;
                                }
                                else  // Meaning the keys match, then leave
                                {
                                        check = 1;
                                }
                        }
                        else  // Empty node, meaning the key is NOT in the table
                        {
                                check = 1;
                        }
                }
        }
        if (t->table[index] != NULL) // Meaning the key is in the table, so update the value
        {
                old_value = t->table[index]->value;
                t->table[index]->value = value;
        }
        else
        {
                t->size++;
                if ((float)t->size / t->capacity > LOAD_THRESHOLD)  // Time to rehash 
                {
                     // Not sure what to do here
                     // I was told that I must use realloc, but I am unsure how
                }
                t->table[index] = malloc(sizeof(Entry));
                t->table[index]->key = key;
                t->table[index]->value = value;
                t->print(key, value);
        }
        return old_value;
}

首先,在if测试中,看看我是否应该重新进行,我想用

重新分配内存

t->table = (Entry**)realloc((t->capacity * RESIZE_FACTOR), sizeof(Entry));

然而这给了我错误

error: passing argument 1 of 'realloc' makes pointer from integer without a cast [-Werror]

我不确定如何修复/接近。

还有将键/值对重新分配给新索引的问题,因为我相信一旦容量发生变化,表中的当前索引就不再具有代表性了。就像realloc一样,我不确定如何做到这一点。

非常感谢任何帮助,谢谢!

2 个答案:

答案 0 :(得分:0)

size_t是一个整数。传递给realloc的第一个参数应该是一个指针。

void * realloc(void * ptr,size_t size);

您需要将指针传递给realloc,而不是t-&gt; capacity

答案 1 :(得分:0)

“还存在将键/值对重新分配给新索引的问题,因为我相信一旦容量发生变化,表中的当前索引将不再具有代表性。就像重新分配一样,我不确定如何执行此操作。 “

是的,如果您想使用新容量,则必须更改哈希函数,因此索引不再具有代表性。这就是malloc()realloc()更适合这种情况的原因。

可以通过以下步骤简单地调整哈希表的大小:

  1. 更新容量
  2. 更新哈希函数(利用新容量)
  3. 使用malloc 分配具有新功能的新指针表。
  4. 将最后一个表的所有指针一一复制到新表(在更新的哈希函数指定的适当位置)
  5. 释放上一个指针表的内存(但是不要释放入口指针本身!)

评论:

  • realloc()在这种情况下没有用,因为散列函数已更改,您对保留指针的位置不感兴趣。
  • 应该谨慎地进行大小调整(一个malloc调用,一堆指针副本...),因此每次调整大小时,容量至少增加1.5倍或2倍。
  • The C Programming Language (2nd Edition)的6.6节中展示了一个很好而简单的哈希表实现。

要获得更好的参考,您可以检查领先的程序员是如何完成的,例如Python的字典实现(使用C):How are Python's Built In Dictionaries Implemented?source code