Implementation of Hash Table in C/C++ using Separate Chaining (original) (raw)

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.

Some Examples of Hash Functions

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

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

Hash Map

Implementation without Rehashing:

C++ `

#include #include #include

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:

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.

Related Article: Separate Chaining Collision Handling Technique in Hashing.