Hướng dẫn resize hash table c++ - thay đổi kích thước bảng băm c ++

I'm doing hash table with chaining and can't figure out how should I rehash whole table while resizing. I was thinking about inserting all elements with new hashcode in resize method, but I have no idea how to... Could you give me a hint or something? Here is rehash (I mean resize, without rehashing yet) method:

void rehash()
{
    if (current_size >= load * size) {
        int newsize = size * cap;
        Node** tmp = new Node * [newsize];
        for (int i = 0; i < size; i++) 
        {
            tmp[i] = hashtable[i];
        }
        for (int i = size; i < newsize; ++i) 
        {
            tmp[i] = NULL;
        }
        delete[] hashtable;
        hashtable = tmp;
        size = newsize;
    }
}

and, if thats helpful, inserting method:

void addTo(string key, V value)
{
    rehash();
    int index = hashFunction(key);
    if (hashtable[index] == NULL)
    {
        Node* newpair = new Node(key, value);
        hashtable[index] = newpair;
        hashtable[index]->data = newpair;
    }
    else
    {
        Node* tmp = hashtable[index];
        Node* newpair = new Node(key, value);
        Node* newnode = new Node;
        newnode->data = newpair;
        newnode->next = NULL;
        while (tmp->next != NULL)
        {
            tmp = tmp->next;
        }
        tmp->next = newnode;
        
    }
    current_size++;
}

Thank you.

asked Nov 29, 2020 at 17:39

Hướng dẫn resize hash table c++ - thay đổi kích thước bảng băm c ++

5

When you increase the size of your hash table, the associated buckets may change for some keys. Your code just copies the lists from the front part, which means that some values can no longer be found in the table. (For example a key with hash code 13 will have the index 1 in a table of size 4, but the index will change to 5 after increasing the size to 8.)

Your basic approach to allocate a new array is correct, but you must place the nodes in their correct buckets. Becsuae you have a linked list, you can visit each bucket of the old table and extract the first node while there is one and then put it into the bucket with the right new index:

void rehash()
{
    if (current_size >= load * size) {
        size_t newsize = size * cap;
        Node** tmp = new Node * [newsize];

        for (size_t i = 0; i < newsize; ++i) {
            tmp[i] = NULL;
        }

        for (size_t i = 0; i < size; i++) {
            while (hashtable[i]) {
                Node *node = hashtable[i];
                size_t index = hashFunction(node->key);

                // remove node from old table ...
                hashtable[i] = node->next;

                // ... and insert into new one
                node->next = tmp[index];
                tmp[index] = node;                    
            }
        }

        // replace hash table
        delete[] hashtable;
        hashtable = tmp;
        size = newsize;
    }
}

This shold work. (But I haven't tested it.)

answered Nov 29, 2020 at 19:37

Hướng dẫn resize hash table c++ - thay đổi kích thước bảng băm c ++

M OehmM Oehm

28.4k3 gold badges30 silver badges42 bronze badges

0

#include "hashtable.h" #bao gồm // assert #bao gồm // printf #bao gồm // strlen, strcmpvoidtestmake () {printf ("%s ...", __function__); size_t dung lượng = 3; Hashtable* htp = hashtablemake (công suất); khẳng định (htp! = null); khẳng định (htp-> công suất == 3); printf ("ok \ n"); } voidTestFree () {printf ("%s ...", __function__); size_t dung lượng = 3; Hashtable* htp = hashtablemake (công suất); HashtableFree (HTP); printf ("ok \ n"); } voidTestSet () {printf ("%s ...", __function__); size_t dung lượng = 3; Hashtable* htp = hashtablemake (công suất); char* bàn phím = "xin chào"; size_t kEngrength = strlen (bàn phím) + 1; size_t keyhash = TerribleHash (bàn phím, keyrengm); char* valuep = "thế giới"; Hashtableset (HTP, bàn phím, keylight, khóa, valuep); khẳng định (htp-> dân số == 1); printf ("ok \ n"); } voidTestget () {printf ("%s ...", __function__); size_t dung lượng = 3; Hashtable* htp = hashtablemake (công suất); char* bàn phím = "xin chào"; size_t kEngrength = strlen (bàn phím) + 1; size_t keyhash = TerribleHash (bàn phím, keyrengm); char* valuep = "thế giới"; Hashtableset (HTP, bàn phím, keylight, khóa, valuep); char* gotp = hashtableget (htp, bàn phím, keyrength, khóa); khẳng định (strcmp (valuep, gotp) == 0); printf ("ok \ n"); } voidTestSlotCollision () {printf ("%s ...", __function__); size_t dung lượng = 1; Hashtable* htp = hashtablemake (công suất); char* key1p = "xin chào"; size_t key1length = strlen (key1p) + 1; size_t key1hash = TerribleHash (key1p, key1length); char* value1p = "thế giới"; Hashtableset (HTP, KEY1P, KEY1LEPT, KEY1HASH, value1p); khẳng định (htp-> dân số == 1); char* key2p = "foo"; size_t key2length = strlen (key2p) + 1; size_t key2hash = TerribleHash (key2p, key2length); char* value2p = "thanh"; Hashtableset (HTP, key2p, key2Lpm, key2hash, value2p); khẳng định (htp-> dân số == 2); char* got1p = hashtableget (htp, key1p, key1length, key1hash); khẳng định (strcmp (value1p, got1p) == 0); char* got2p = hashtableget (htp, key2p, key2length, key2hash); khẳng định (strcmp (value2p, got2p) == 0); printf ("ok \ n"); } voidTesThashCollision () {printf ("%s ...", __function__); size_t dung lượng = 1; Hashtable* htp = hashtablemake (công suất); char* key1p = "ab"; size_t key1length = strlen (key1p) + 1; size_t key1hash = TerribleHash (key1p, key1length); char* value1p = "cd"; Hashtableset (HTP, KEY1P, KEY1LEPT, KEY1HASH, value1p); khẳng định (htp-> dân số == 1); char* key2p = "ba"; size_t key2length = strlen (key2p) + 1; size_t key2hash = TerribleHash (key2p, key2length); char* value2p = "dc"; Hashtableset (HTP, key2p, key2Lpm, key2hash, value2p); khẳng định (htp-> dân số == 2); char* got1p = hashtableget (htp, key1p, key1length, key1hash); khẳng định (strcmp (value1p, got1p) == 0); char* got2p = hashtableget (htp, key2p, key2length, key2hash); khẳng định (strcmp (value2p, got2p) == 0); printf ("ok \ n"); } voidTestGrow () {printf ("%s ...", __function__); size_t dung lượng = 1; Hashtable* htp = hashtablemake (công suất); khẳng định (htp-> dân số == 0); khẳng định (htp-> công suất == dung lượng); char* key1p = "xin chào"; size_t key1length = strlen (key1p) + 1; size_t key1hash = TerribleHash (key1p, key1length); char* value1p = "thế giới"; Hashtableset (HTP, KEY1P, KEY1LEPT, KEY1HASH, value1p); khẳng định (htp-> dân số == 1); khẳng định (htp-> công suất == dung lượng); char* key2p = "foo"; size_t key2length = strlen (key2p) + 1; size_t key2hash = TerribleHash (key2p, key2length); char* value2p = "thanh"; Hashtableset (HTP, key2p, key2Lpm, key2hash, value2p); khẳng định (htp-> dân số == 2); khẳng định (htp-> công suất == công suất*2); printf ("ok \ n"); } voidTestShRink () {printf ("%s ...", __function__); size_t dung lượng = 1; Hashtable* htp = hashtablemake (công suất); khẳng định (htp-> dân số == 0); khẳng định (htp-> công suất == dung lượng); char* key1p = "xin chào"; size_t key1length = strlen (key1p) + 1; size_t key1hash = TerribleHash (key1p, key1length); char* value1p = "thế giới"; Hashtableset (HTP, KEY1P, KEY1LEPT, KEY1HASH, value1p); khẳng định (htp-> dân số == 1); khẳng định (htp-> công suất == dung lượng); char* key2p = "foo"; size_t key2length = strlen (key2p) + 1; size_t key2hash = TerribleHash (key2p, key2length); char* value2p = "thanh"; Hashtableset (HTP, key2p, key2Lpm, key2hash, value2p); khẳng định (htp-> dân số == 2); khẳng định (htp-> công suất == công suất*2); Hashtableset (HTP, KEY2P, KEY2LEPT, KEY2HASH, NULL); khẳng định (htp-> dân số == 1); khẳng định (htp-> công suất == dung lượng); printf ("ok \ n"); } intmain (int argc, char ** argv) {testMake (); testfree (); Tập kiểm tra(); testget (); testSlotCollision (); TestHashCollision (); testgrow (); testshrink (); return0; }include "HashTable.h" #include <assert.h> // assert #include <stdio.h> // printf #include <string.h> // strlen, strcmp void testMake() { printf("%s... ", __FUNCTION__); size_t capacity = 3; HashTable* htp = HashTableMake(capacity); assert(htp != NULL); assert(htp->capacity == 3); printf("OK\n"); } void testFree() { printf("%s... ", __FUNCTION__); size_t capacity = 3; HashTable* htp = HashTableMake(capacity); HashTableFree(htp); printf("OK\n"); } void testSet() { printf("%s... ", __FUNCTION__); size_t capacity = 3; HashTable* htp = HashTableMake(capacity); char* keyp = "hello"; size_t keyLength = strlen(keyp) + 1; size_t keyHash = terribleHash(keyp, keyLength); char* valuep = "world"; HashTableSet(htp, keyp, keyLength, keyHash, valuep); assert(htp->population == 1); printf("OK\n"); } void testGet() { printf("%s... ", __FUNCTION__); size_t capacity = 3; HashTable* htp = HashTableMake(capacity); char* keyp = "hello"; size_t keyLength = strlen(keyp) + 1; size_t keyHash = terribleHash(keyp, keyLength); char* valuep = "world"; HashTableSet(htp, keyp, keyLength, keyHash, valuep); char* gotp = HashTableGet(htp, keyp, keyLength, keyHash); assert(strcmp(valuep, gotp) == 0); printf("OK\n"); } void testSlotCollision() { printf("%s... ", __FUNCTION__); size_t capacity = 1; HashTable* htp = HashTableMake(capacity); char* key1p = "hello"; size_t key1Length = strlen(key1p) + 1; size_t key1Hash = terribleHash(key1p, key1Length); char* value1p = "world"; HashTableSet(htp, key1p, key1Length, key1Hash, value1p); assert(htp->population == 1); char* key2p = "foo"; size_t key2Length = strlen(key2p) + 1; size_t key2Hash = terribleHash(key2p, key2Length); char* value2p = "bar"; HashTableSet(htp, key2p, key2Length, key2Hash, value2p); assert(htp->population == 2); char* got1p = HashTableGet(htp, key1p, key1Length, key1Hash); assert(strcmp(value1p, got1p) == 0); char* got2p = HashTableGet(htp, key2p, key2Length, key2Hash); assert(strcmp(value2p, got2p) == 0); printf("OK\n"); } void testHashCollision() { printf("%s... ", __FUNCTION__); size_t capacity = 1; HashTable* htp = HashTableMake(capacity); char* key1p = "ab"; size_t key1Length = strlen(key1p) + 1; size_t key1Hash = terribleHash(key1p, key1Length); char* value1p = "cd"; HashTableSet(htp, key1p, key1Length, key1Hash, value1p); assert(htp->population == 1); char* key2p = "ba"; size_t key2Length = strlen(key2p) + 1; size_t key2Hash = terribleHash(key2p, key2Length); char* value2p = "dc"; HashTableSet(htp, key2p, key2Length, key2Hash, value2p); assert(htp->population == 2); char* got1p = HashTableGet(htp, key1p, key1Length, key1Hash); assert(strcmp(value1p, got1p) == 0); char* got2p = HashTableGet(htp, key2p, key2Length, key2Hash); assert(strcmp(value2p, got2p) == 0); printf("OK\n"); } void testGrow() { printf("%s... ", __FUNCTION__); size_t capacity = 1; HashTable* htp = HashTableMake(capacity); assert(htp->population == 0); assert(htp->capacity == capacity); char* key1p = "hello"; size_t key1Length = strlen(key1p) + 1; size_t key1Hash = terribleHash(key1p, key1Length); char* value1p = "world"; HashTableSet(htp, key1p, key1Length, key1Hash, value1p); assert(htp->population == 1); assert(htp->capacity == capacity); char* key2p = "foo"; size_t key2Length = strlen(key2p) + 1; size_t key2Hash = terribleHash(key2p, key2Length); char* value2p = "bar"; HashTableSet(htp, key2p, key2Length, key2Hash, value2p); assert(htp->population == 2); assert(htp->capacity == capacity*2); printf("OK\n"); } void testShrink() { printf("%s... ", __FUNCTION__); size_t capacity = 1; HashTable* htp = HashTableMake(capacity); assert(htp->population == 0); assert(htp->capacity == capacity); char* key1p = "hello"; size_t key1Length = strlen(key1p) + 1; size_t key1Hash = terribleHash(key1p, key1Length); char* value1p = "world"; HashTableSet(htp, key1p, key1Length, key1Hash, value1p); assert(htp->population == 1); assert(htp->capacity == capacity); char* key2p = "foo"; size_t key2Length = strlen(key2p) + 1; size_t key2Hash = terribleHash(key2p, key2Length); char* value2p = "bar"; HashTableSet(htp, key2p, key2Length, key2Hash, value2p); assert(htp->population == 2); assert(htp->capacity == capacity*2); HashTableSet(htp, key2p, key2Length, key2Hash, NULL); assert(htp->population == 1); assert(htp->capacity == capacity); printf("OK\n"); } int main(int argc, char** argv) { testMake(); testFree(); testSet(); testGet(); testSlotCollision(); testHashCollision(); testGrow(); testShrink(); return 0; }