-
Notifications
You must be signed in to change notification settings - Fork 306
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1317 from Riya7045/main
Added Hashmap data structure
- Loading branch information
Showing
2 changed files
with
205 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
// Define the structure for a node in the linked list (for chaining) | ||
typedef struct Node { | ||
int key; | ||
int value; | ||
struct Node* next; | ||
} Node; | ||
|
||
// Define the structure for the Hashmap | ||
typedef struct HashMap { | ||
int size; // Size of the hashmap (number of buckets) | ||
Node** buckets; // Array of pointers to the linked lists (buckets) | ||
} HashMap; | ||
|
||
// Create a new node (for the linked list) | ||
Node* createNode(int key, int value) { | ||
Node* newNode = (Node*)malloc(sizeof(Node)); | ||
newNode->key = key; | ||
newNode->value = value; | ||
newNode->next = NULL; | ||
return newNode; | ||
} | ||
|
||
// Create the HashMap | ||
HashMap* createHashMap(int size) { | ||
HashMap* map = (HashMap*)malloc(sizeof(HashMap)); | ||
map->size = size; | ||
map->buckets = (Node**)malloc(size * sizeof(Node*)); | ||
|
||
// Initialize all buckets to NULL | ||
for (int i = 0; i < size; i++) { | ||
map->buckets[i] = NULL; | ||
} | ||
|
||
return map; | ||
} | ||
|
||
// Hash function to map a key to an index based on table size (modulo operator) | ||
int hashFunction(int key, int size) { | ||
return key % size; | ||
} | ||
|
||
// Insert a key-value pair into the HashMap | ||
void insert(HashMap* map, int key, int value) { | ||
int index = hashFunction(key, map->size); | ||
Node* newNode = createNode(key, value); | ||
|
||
// If there's no collision, insert the node at the bucket | ||
if (map->buckets[index] == NULL) { | ||
map->buckets[index] = newNode; | ||
} else { | ||
// Handle collision using chaining (linked list) | ||
Node* current = map->buckets[index]; | ||
while (current->next != NULL) { | ||
current = current->next; | ||
} | ||
current->next = newNode; | ||
} | ||
printf("Inserted key: %d, value: %d at index: %d\n", key, value, index); | ||
} | ||
|
||
// Search for a value by key in the HashMap | ||
int search(HashMap* map, int key) { | ||
int index = hashFunction(key, map->size); | ||
Node* current = map->buckets[index]; | ||
|
||
while (current != NULL) { | ||
if (current->key == key) { | ||
return current->value; | ||
} | ||
current = current->next; | ||
} | ||
|
||
return -1; // Key not found | ||
} | ||
|
||
// Delete a key-value pair from the HashMap | ||
void Delete(HashMap* map, int key) { | ||
int index = hashFunction(key, map->size); | ||
Node* current = map->buckets[index]; | ||
Node* prev = NULL; | ||
|
||
while (current != NULL) { | ||
if (current->key == key) { | ||
if (prev == NULL) { | ||
map->buckets[index] = current->next; // Remove head of the list | ||
} else { | ||
prev->next = current->next; // Bypass the node to delete it | ||
} | ||
free(current); | ||
printf("Key %d deleted\n", key); | ||
return; | ||
} | ||
prev = current; | ||
current = current->next; | ||
} | ||
|
||
printf("Key %d not found\n", key); | ||
} | ||
|
||
// Free the memory used by the HashMap | ||
void freeHashMap(HashMap* map) { | ||
for (int i = 0; i < map->size; i++) { | ||
Node* current = map->buckets[i]; | ||
while (current != NULL) { | ||
Node* temp = current; | ||
current = current->next; | ||
free(temp); | ||
} | ||
} | ||
free(map->buckets); | ||
free(map); | ||
} | ||
|
||
// Main function to demonstrate the usage | ||
int main() { | ||
// Create a HashMap with 10 buckets | ||
HashMap* map = createHashMap(10); | ||
|
||
// Insert some key-value pairs | ||
insert(map, 1, 10); | ||
insert(map, 2, 20); | ||
insert(map, 12, 120); // This will collide with key 2 | ||
insert(map, 22, 220); // Another collision example | ||
|
||
// Search for a key | ||
int value = search(map, 12); | ||
if (value != -1) { | ||
printf("Key 12 found with value: %d\n", value); | ||
} else { | ||
printf("Key 12 not found\n"); | ||
} | ||
|
||
// Delete a key-value pair | ||
Delete(map, 2); | ||
Delete(map, 22); | ||
|
||
// Free the memory used by the HashMap | ||
freeHashMap(map); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# HashMap Implementation in C | ||
This project is a simple implementation of a HashMap (or Hash Table) in C, using chaining to handle collisions.The implementation includes common HashMap operations | ||
such as insertion, search, and deletion of key-value pairs. The chaining mechanism uses linked lists to resolve hash collisions. | ||
|
||
## Features | ||
Chaining-based collision handling: Handles collisions using linked lists in each bucket. | ||
|
||
Hashing: Uses a simple modulo-based hash function. | ||
|
||
Operations: | ||
|
||
Insertion of key-value pairs. | ||
|
||
Searching for a value by its key. | ||
|
||
Deleting key-value pairs. | ||
|
||
Memory management: Clean up memory to avoid memory leaks. | ||
|
||
## 1. Insertion | ||
The insertion operation involves adding a new key-value pair to the HashMap. The process is as follows: | ||
|
||
Hashing: The key is hashed using the hash function. In this case, the hash function uses the modulo operation to map the key to a specific index in the bucket array: | ||
The result of the hash function is the index in the bucket array where the key-value pair will be inserted. | ||
|
||
Collision Handling: If two keys produce the same index (i.e., a collision occurs), the linked list at that bucket is extended to accommodate the new key-value pair. | ||
This is called chaining. Each bucket points to the head of a linked list, and new nodes are added to the end of the list if there is a collision. | ||
|
||
Time Complexity: | ||
Best case (no collision): O(1) | ||
Worst case (multiple collisions): O(n) where n is the number of nodes in the linked list (in the case of a very poor hash function or many collisions). | ||
|
||
## 2. Deletion | ||
The deletion operation removes a key-value pair from the HashMap by: | ||
|
||
Hashing: The key to be deleted is hashed to find the index of the bucket. | ||
Traversal: The linked list at the bucket is traversed to find the node that contains the given key. | ||
Removal: Once the node with the given key is found: | ||
If it's the head of the list, the bucket is updated to point to the next node. | ||
If it's in the middle or at the end of the list, the previous node's next pointer is updated to bypass the node to be deleted. | ||
|
||
Memory Deallocation: The memory allocated for the deleted node is freed. | ||
|
||
Time Complexity: | ||
Best case: O(1) (when the key is found immediately and there's no collision) | ||
Worst case: O(n) (when multiple nodes are in the same bucket, and the key is found at the end) | ||
|
||
## 3. Searching | ||
Searching for a key in the HashMap involves: | ||
|
||
Hashing: The key to be searched is hashed to find the index of the bucket. | ||
Traversal: The linked list at the bucket is traversed, checking each node's key. If the key is found, the corresponding value is returned; | ||
otherwise, a value of -1 (indicating "not found") is returned. | ||
|
||
The linked list traversal continues until either: | ||
|
||
The key is found, or | ||
The end of the list is reached (in which case the key doesn't exist in the HashMap). | ||
Time Complexity: | ||
Best case: O(1) (if the key is at the head of the list or no collision occurred) | ||
Worst case: O(n) (if there are multiple collisions, and the key is at the end of the list) |