Implementation of Hash Table in C/C++ using Separate Chaining

Last Updated : 28 May, 2026

Hashing is a technique used to map a large amount of data to a smaller, fixed-size value using a hash function.

  • The process is irreversible - the original data cannot be reconstructed from the hash.
  • Since large data is mapped into a smaller space, collisions can occur (different inputs producing the same hash).
  • Collisions are common and unavoidable when the input set is larger than the output range.

Some Examples of Hash Functions

  • key % number of buckets
  • ASCII value of character * PrimeNumberx. Where x = 1, 2, 3....n
  • You can make your own hash function but it should be a good hash function that gives less number of collisions.
Components of Hashing

Bucket Index

The value returned by the Hash function is the bucket index for a key in a separate chaining method. Each index in the array is called a bucket as it is a bucket of a linked list.

Rehashing

Rehashing is a technique used in hash tables to reduce collisions when the number of elements increases. In rehashing, a new hash table with larger capacity (usually double the previous size) is created, and all existing elements are reinserted using the updated hash function.

Note: Rehashing generally occurs when the load factor becomes greater than 0.5.

Steps in Rehashing

  • Double the size of the hash table.
  • Reinsert all existing elements into the new table using the hash function.
  • Delete the old table and replace it with the new one.

Load Factor Formula

Load Factor = Number of Elements / Total Number of Buckets

Collision

Collision is the situation when the bucket index is not empty. It means that a linked list head is present at that bucket index. We have two or more values that map to the same bucket index.

Major Functions in our Program

  • Insertion
  • Search
  • Hash Function
  • Delete
  • Rehashing
Hash Map

Implementation without Rehashing:

C++
#include <iostream>
#include <cstring>
#include <cstdlib>

using namespace std;

// Linked List node
struct node {

    // key is string
    char* key;

    // value is also string
    char* value;

    struct node* next;
};

// Like constructor
void setNode(struct node* node, char* key, char* value) {

    node->key = key;
    node->value = value;
    node->next = NULL;

    return;
}

struct hashMap {

    // Current number of elements in hashMap
    // and capacity of hashMap
    int numOfElements, capacity;

    // Holds base address array of linked lists
    struct node** arr;
};

// Like constructor
void initializeHashMap(struct hashMap* mp) {

    // Default capacity
    mp->capacity = 100;

    mp->numOfElements = 0;

    // Array of linked list pointers
    mp->arr = (struct node**)calloc(
        mp->capacity,
        sizeof(struct node*)
    );

    return;
}

int hashFunction(struct hashMap* mp, char* key) {

    int bucketIndex;

    int sum = 0, factor = 31;

    for (int i = 0; i < strlen(key); i++) {

        sum = (
            (sum % mp->capacity)
            + (((int)key[i]) * factor) % mp->capacity
        ) % mp->capacity;

        factor = (
            (factor % __INT16_MAX__)
            * (31 % __INT16_MAX__)
        ) % __INT16_MAX__;
    }

    bucketIndex = sum;

    return bucketIndex;
}

void insert(struct hashMap* mp, char* key, char* value) {

    // Getting bucket index
    int bucketIndex = hashFunction(mp, key);

    // Creating a new node
    struct node* newNode =
        (struct node*)malloc(sizeof(struct node));

    // Setting node values
    setNode(newNode, key, value);

    // No collision
    if (mp->arr[bucketIndex] == NULL) {

        mp->arr[bucketIndex] = newNode;
    }

    // Collision occurred
    else {

        // Insert at head of linked list
        newNode->next = mp->arr[bucketIndex];

        mp->arr[bucketIndex] = newNode;
    }

    // Update number of elements
    mp->numOfElements++;

    return;
}

void deleteKey(struct hashMap* mp, char* key) {

    // Getting bucket index
    int bucketIndex = hashFunction(mp, key);

    struct node* prevNode = NULL;

    // Head node of linked list
    struct node* currNode = mp->arr[bucketIndex];

    while (currNode != NULL) {

        // Key found
        if (strcmp(key, currNode->key) == 0) {

            // Head node deletion
            if (currNode == mp->arr[bucketIndex]) {

                mp->arr[bucketIndex] = currNode->next;
            }

            // Middle or last node deletion
            else {

                prevNode->next = currNode->next;
            }

            free(currNode);

            // Update number of elements
            mp->numOfElements--;

            break;
        }

        prevNode = currNode;

        currNode = currNode->next;
    }

    return;
}

char* search(struct hashMap* mp, char* key) {

    // Getting bucket index
    int bucketIndex = hashFunction(mp, key);

    // Head of linked list
    struct node* bucketHead =
        mp->arr[bucketIndex];

    while (bucketHead != NULL) {

        // Key found
        if (strcmp(bucketHead->key, key) == 0) {

            return bucketHead->value;
        }

        bucketHead = bucketHead->next;
    }

    // Key not found
    char* errorMssg =
        (char*)malloc(sizeof(char) * 25);

    strcpy(errorMssg,
           "Oops! No data found.\n");

    return errorMssg;
}

// Driver code
int main() {

    // Initialize hash map
    struct hashMap* mp =
        (struct hashMap*)malloc(sizeof(struct hashMap));

    initializeHashMap(mp);

    insert(mp, "Yogaholic", "Anjali");
    insert(mp, "pluto14", "Vartika");
    insert(mp, "elite_Programmer", "Manish");
    insert(mp, "GFG", "GeeksforGeeks");
    insert(mp, "decentBoy", "Mayank");

    printf("%s\n", search(mp, "elite_Programmer"));
    printf("%s\n", search(mp, "Yogaholic"));
    printf("%s\n", search(mp, "pluto14"));
    printf("%s\n", search(mp, "decentBoy"));
    printf("%s\n", search(mp, "GFG"));

    // Key not inserted
    printf("%s\n", search(mp, "randomKey"));

    printf("\nAfter deletion : \n");

    // Delete key
    deleteKey(mp, "decentBoy");

    // Search deleted key
    printf("%s\n", search(mp, "decentBoy"));

    return 0;
}
C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Linked List node
struct node {

    // key is string
    char* key;

    // value is also string
    char* value;
    struct node* next;
};

// like constructor
void setNode(struct node* node, char* key, char* value)
{
    node->key = key;
    node->value = value;
    node->next = NULL;
    return;
};

struct hashMap {

    // Current number of elements in hashMap
    // and capacity of hashMap
    int numOfElements, capacity;

    // hold base address array of linked list
    struct node** arr;
};

// like constructor
void initializeHashMap(struct hashMap* mp)
{

    // Default capacity in this case
    mp->capacity = 100;
    mp->numOfElements = 0;

    // array of size = 1
    mp->arr = (struct node**)malloc(sizeof(struct node*)
                                    * mp->capacity);
    return;
}

int hashFunction(struct hashMap* mp, char* key)
{
    int bucketIndex;
    int sum = 0, factor = 31;
    for (int i = 0; i < strlen(key); i++) {

        // sum = sum + (ascii value of
        // char * (primeNumber ^ x))...
        // where x = 1, 2, 3....n
        sum = ((sum % mp->capacity)
               + (((int)key[i]) * factor) % mp->capacity)
              % mp->capacity;

        // factor = factor * prime
        // number....(prime
        // number) ^ x
        factor = ((factor % __INT16_MAX__)
                  * (31 % __INT16_MAX__))
                 % __INT16_MAX__;
    }

    bucketIndex = sum;
    return bucketIndex;
}

void insert(struct hashMap* mp, char* key, char* value)
{

    // Getting bucket index for the given
    // key - value pair
    int bucketIndex = hashFunction(mp, key);
    struct node* newNode = (struct node*)malloc(

        // Creating a new node
        sizeof(struct node));

    // Setting value of node
    setNode(newNode, key, value);

    // Bucket index is empty....no collision
    if (mp->arr[bucketIndex] == NULL) {
        mp->arr[bucketIndex] = newNode;
    }

    // Collision
    else {

        // Adding newNode at the head of
        // linked list which is present
        // at bucket index....insertion at
        // head in linked list
        newNode->next = mp->arr[bucketIndex];
        mp->arr[bucketIndex] = newNode;
    }
    return;
}

void delete (struct hashMap* mp, char* key)
{

    // Getting bucket index for the
    // given key
    int bucketIndex = hashFunction(mp, key);

    struct node* prevNode = NULL;

    // Points to the head of
    // linked list present at
    // bucket index
    struct node* currNode = mp->arr[bucketIndex];

    while (currNode != NULL) {

        // Key is matched at delete this
        // node from linked list
        if (strcmp(key, currNode->key) == 0) {

            // Head node
            // deletion
            if (currNode == mp->arr[bucketIndex]) {
                mp->arr[bucketIndex] = currNode->next;
            }

            // Last node or middle node
            else {
                prevNode->next = currNode->next;
            }
            free(currNode);
            break;
        }
        prevNode = currNode;
        currNode = currNode->next;
    }
    return;
}

char* search(struct hashMap* mp, char* key)
{

    // Getting the bucket index
    // for the given key
    int bucketIndex = hashFunction(mp, key);

    // Head of the linked list
    // present at bucket index
    struct node* bucketHead = mp->arr[bucketIndex];
    while (bucketHead != NULL) {

        // Key is found in the hashMap
        if (bucketHead->key == key) {
            return bucketHead->value;
        }
        bucketHead = bucketHead->next;
    }

    // If no key found in the hashMap
    // equal to the given key
    char* errorMssg = (char*)malloc(sizeof(char) * 25);
    errorMssg = "Oops! No data found.\n";
    return errorMssg;
}

// Drivers code
int main()
{

    // Initialize the value of mp
    struct hashMap* mp
        = (struct hashMap*)malloc(sizeof(struct hashMap));
    initializeHashMap(mp);

    insert(mp, "Yogaholic", "Anjali");
    insert(mp, "pluto14", "Vartika");
    insert(mp, "elite_Programmer", "Manish");
    insert(mp, "GFG", "GeeksforGeeks");
    insert(mp, "decentBoy", "Mayank");

    printf("%s\n", search(mp, "elite_Programmer"));
    printf("%s\n", search(mp, "Yogaholic"));
    printf("%s\n", search(mp, "pluto14"));
    printf("%s\n", search(mp, "decentBoy"));
    printf("%s\n", search(mp, "GFG"));

    // Key is not inserted
    printf("%s\n", search(mp, "randomKey"));

    printf("\nAfter deletion : \n");

    // Deletion of key
    delete (mp, "decentBoy");
    printf("%s\n", search(mp, "decentBoy"));

    return 0;
}

Output
Manish
Anjali
Vartika
Mayank
GeeksforGeeks
Oops! No data found.


After deletion : 
Oops! No data found.

Explanation:

  • Insertion: Inserts the key-value pair at the head of the linked list at the calculated bucket index and increments numOfElements.
  • hashFunction: Calculates the bucket index using ASCII values of characters multiplied by powers of the prime number 31.
  • Deletion: Removes the key-value pair associated with the given key from the hash table. After successful deletion, numOfElements is decremented.
  • Search: Searches for the value associated with the given key in the hash table.

This implementation does not use rehashing and works with a fixed-size array of linked lists. In the given example, both keys and values are strings.

Time Complexity and Space Complexity:

The time complexity of hash table insertion and deletion operations is O(1) on average. There is some mathematical calculation that proves it.

  • Time Complexity of Insertion: In the average case it is constant. In the worst case, it is linear.
  • Time Complexity of Search: In the average case it is constant. In the worst case, it is linear.
  • Time Complexity of Deletion: In average cases it is constant. In the worst case, it is linear.
  • Space Complexity: O(n) as it has n number of elements.

Related Article: Separate Chaining Collision Handling Technique in Hashing.

Comment