ldc57
ldc57

Reputation: 23

Trying to understand hash table code in c++

I'm learning hash tables and found this code on another website, but am having trouble understanding the Insert(int key, int value) function. The function works well but I am wondering if there is extra code that is not needed or if I am not understanding it completely.

Specifically, the else condition at the end of the function:

else
{
     entry->value = value;
 }

It doesn't seem to ever reach that condition when I call that function using different parameters. Here is the rest of the code.

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstdio>
using namespace std;
const int TABLE_SIZE = 128;

class HashNode
{
public:
    int key;
    int value;
    HashNode* next;
    HashNode(int key, int value)
    {
        this->key = key;
        this->value = value;
        this->next = NULL;
    }
};

class HashMap
{
private:
    HashNode** htable;
    public:
    HashMap()
    {
        htable = new HashNode*[TABLE_SIZE];
        for (int i = 0; i < TABLE_SIZE; i++)
            htable[i] = NULL;
    }
    ~HashMap()
    {
        for (int i = 0; i < TABLE_SIZE; ++i)
        {
            HashNode* entry = htable[i];
            while (entry != NULL)
            {
                HashNode* prev = entry;
                entry = entry->next;
                delete prev;
            }
        }
        delete[] htable;
    }
    /*
     * Hash Function
     */
    int HashFunc(int key)
    {
        return key % TABLE_SIZE;
    }

    /*
     * Insert Element at a key
     */
    void Insert(int key, int value)
    {
        int hash_val = HashFunc(key);
        HashNode* prev = NULL;
        HashNode* entry = htable[hash_val];
        while (entry != NULL)
        {
            prev = entry;
            entry = entry->next;
        }
        if (entry == NULL)
        {
            entry = new HashNode(key, value);
            if (prev == NULL)
            {
                htable[hash_val] = entry;
            }
            else
            {
                prev->next = entry;
            }
        }
        else
        {
            entry->value = value;
        }
    }

    /* Search Element at a key
     */
    int Search(int key)
    {
        bool flag = false;
        int hash_val = HashFunc(key);
        HashNode* entry = htable[hash_val];
        while (entry != NULL)
        {
            if (entry->key == key)
            {
                cout << entry->value << " ";
                flag = true;
            }
            entry = entry->next;
        }
        if (!flag)
            return -1;
    }
};

int main()
{
    HashMap hash;
    hash.Insert(3, 7);
    hash.Search(3);
}

Any clarification is highly appreciated.

Thank you

Upvotes: 1

Views: 1095

Answers (1)

user4581301
user4581301

Reputation: 33982

while (entry != NULL)

precedes

if (entry == NULL) 

There is no way out of the while (entry != NULL) loop unless entry is NULL, guaranteeing that the else case is impossible.

I believe that inside the while loop a test to see if the key is already present is required.

while (entry != NULL)
{
    if (entry->key == key)
    {
        break;
    }
    prev = entry;
    entry = entry->next;
}

Off topic: Take a look at this question and answer for a suggestion on how to simplify your code: Using pointers to remove item from singly-linked list

Example:

/*
 * Insert Element at a key
 */
void Insert(int key, int value)
{
    int hash_val = HashFunc(key);
    HashNode** nextPtr = &htable[hash_val]; // Get a pointer to next, not to the entry
    // with a pointer to next we can keep going from next to next without 
    // ever needing a previous.
    // pick up a whole bunch of extra dereferencing *nextPtr, but an 
    // optimizing compiler is great at dealing with that extra overhead.
    while ((*nextPtr) != NULL) // loop until found or end
    {
        if ((*nextPtr)->key == key) // found key already in list
        {
            (*nextPtr)->value = value; // set value for key
            return; // all done.
        }
        nextPtr = &(*nextPtr)->next; // keep looking
    }
    *nextPtr = new HashNode(key, value); // didn't find. Add new node to end.
}

Addendum: Search only returns in the failure case. A function that is declared as returning a value must always return a value.

Upvotes: 2

Related Questions