简体   繁体   中英

How can I fix this resize function?

I'm learning data structure. I need to create a resize function for a hash table (chaining/buckets). My code compiles, but the table size never changed. Can someone take a look and give me some tips on what I'm missing in the resize function? Thank you!

    struct hlink {
    TYPE value;
    struct hlink *next;
};

struct hashTable {
    struct hlink **table;
    int tableSize;
    int count;
};


void initHashTable (struct hashTable *ht, int size ) {
    assert (size > 0);

    //allocate memory for table 
    ht->table = (struct hlink **) malloc(size * sizeof(struct hlink *));
    assert(ht->table != 0);

    //initialize empty link list
    int i;
    for (i = 0; i < size; i++)
    {
        ht->table[i] = 0;
    }

    //set tableSize to be size
    ht->tableSize = size;
    ht->count = 0;
}


    void _resizeHashTable(struct hashTable *ht)
{
    //create and initialize new tablesize
    int new_tblSize = 2 * ht->tableSize;

    //old list
    struct hlink **oldList = ht->table;

    //new list
    struct hlink **newList = (struct hlink **) malloc(new_tblSize * sizeof(struct hlink*));

    //Copy old values to new table
    for (int i=0; i < new_tblSize; i++)
    {
        //compute hash value to find the new bucket
        int hashIndex = HASH(oldList[i]->value) % new_tblSize;
        if (hashIndex < 0)
            hashIndex += new_tblSize;

        newList[i]->value = oldList[i]->value;
        newList[i]->next = newList[hashIndex];
    }

    //Assign table and tablesize back to the old table
    free(ht->table);
    ht->table = newList;
    ht->tableSize = new_tblSize;

}


void hashTableAdd (struct hashTable *ht, TYPE newValue)
{
    // compute hash value to find the correct bucket
    int hashIndex = HASH(newValue) % ht->tableSize;
    if (hashIndex < 0)
        hashIndex += ht->tableSize;

    struct hlink * newLink = (struct hlink *) malloc(sizeof(struct hlink));
    assert(newLink != 0);

    newLink->value = newValue;
    newLink->next = ht->table[hashIndex];

    ht->table[hashIndex] = newLink;     //add to bucket 
    ht->count++;


    if ((ht->count / (double) ht->tableSize) > 8.0)
        _resizeHashTable(ht);
}

You are not freeing the old table. You are freeing the one just allocated. Instead of

ht->table = new_tbl;
...
free(new_tbl);

You should

free(ht->table);
ht->table = new_tbl;

You also have a problem in your

//Copy old values to new table
for (int i=0; i < ht->tableSize; i++)
{
    new_tbl[i] = ht->table[i];
}

It is not enough to copy the table bucket entries as above, but each entry in the bucket link list needs to be re-hashed as you have a new table size and thus a potential new hashindex.

int hashIndex = HASH(newValue) % ht->tableSize;

I recommend that you temporarily, when resizing, go though each old bucket and then each link list entry and move it to the new table. Remember, for each entry, the bucket index in the old table may differ from the bucket entry in the new table due to the differing "% ht->tableSize".

During resize(), take care to manage your old table's link-list allocations. They can be re-used in your new table, but proper coding here can be challenging.

Below are just some enhancement ideas...

PS Also recommend

if (ht->count > (ht->tableSize * 8))

instead of

if ((ht->count / (double) ht->tableSize) > 8.0)

PS Also recommend not to double the table size but quadruple it. Further, it is a nice touch to have a table size that is prime. Doing your "%ht->tableSize" with a prime number helps improve the dispersal of weak hash functions.

Quadrupling has a nice touch when you add a hashTableDelete(). With a delete function, you again may call the resize function, but this time, the table is shrinking. It is important that your grow threshold (eg tablesize*8) and your shrink threshold are different. If there are about the same, you can get "thrashing of the hashing" should you happen to add and delete when the table is of that critical size. I like to have my growth threshold at levels like 3, 11, 61, 251, ... (prime under 4**N) and my shrink thresholds at 1, 7, 31, 119, ... (prime under 2*4**N), thus keep re-hashing to a minimum as the table grows and shrinks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM