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.

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

Implementation without Rehashing:
#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;
}
#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.