To Implement Dictionary Using Hashing Algorithms - C Program
The implementation above uses separate chaining—each bucket points to a linked list of entries. Alternatives include:
| Method | Pros | Cons | |--------|------|------| | Separate Chaining | Simple, handles high load, no clustering | Extra memory for pointers | | Linear Probing | Cache-friendly, no pointers | Primary clustering, deletion complex | | Quadratic Probing | Reduces primary clustering | Secondary clustering | | Double Hashing | Excellent distribution | More computation |
For most general-purpose dictionaries, separate chaining is recommended due to its simplicity and predictable performance.
| Operation | Average Case | Worst Case (All Collisions) | |-----------|--------------|-------------------------------| | Insert | O(1) | O(n) | | Search | O(1) | O(n) | | Delete | O(1) | O(n) |
Factors affecting performance:
Benchmarking tip: Run the dictionary with 100,000 insertions and measure average time per operation using clock() or gettimeofday().
Let’s write each function systematically. c program to implement dictionary using hashing algorithms
Ready to take it further? Implement open addressing with quadratic probing, or add a for_each function to iterate over all key-value pairs. Happy coding!
In C, a dictionary is typically implemented using a hash table, which maps unique keys to specific values. Since C doesn't have a built-in dictionary type like Python or Java, you must build one using an array and a hashing function. 1. Define the Data Structures
The foundation of a dictionary consists of a structure for individual entries and the table itself. This example uses separate chaining with linked lists to handle collisions (when two keys hash to the same index).
#include Use code with caution. Copied to clipboard 2. Implement the Hashing Algorithm
A good hash function should distribute keys evenly across the table to minimize collisions. The djb2 algorithm is a popular, efficient choice for string keys.
// djb2 hashing algorithm unsigned int hash(const char *str) unsigned long hash = 5381; int c; while ((c = *str++)) // hash * 33 + c hash = ((hash << 5) + hash) + c; return hash % TABLE_SIZE; Use code with caution. Copied to clipboard 3. Implement Core Operations Benchmarking tip: Run the dictionary with 100,000 insertions
A dictionary requires three primary functions: insert, search, and delete. Insert (Put)
This function adds a new key-value pair or updates the value if the key already exists.
void insert(const char *key, const char *value) unsigned int index = hash(key); Entry *new_entry = dictionary[index]; // Check if key already exists to update it while (new_entry != NULL) if (strcmp(new_entry->key, key) == 0) free(new_entry->value); new_entry->value = strdup(value); return; new_entry = new_entry->next; // Create a new entry if not found new_entry = malloc(sizeof(Entry)); new_entry->key = strdup(key); new_entry->value = strdup(value); new_entry->next = dictionary[index]; // Insert at the head of the list dictionary[index] = new_entry; Use code with caution. Copied to clipboard Search (Get)
In separate chaining, each bucket of the hash table points to a linked list (or another dynamic data structure) of entries that hash to that index.
Advantages:
Disadvantages:
In separate chaining, each bucket of the hash table contains a linked list (or another dynamic data structure) of key-value pairs that hash to that index. When a collision occurs, the new pair is simply appended to the list.
Advantages:
Disadvantages:
In C, a chaining-based dictionary might define nodes as:
typedef struct Entry char *key; int value; struct Entry *next; Entry;
Entry *hashTable[TABLE_SIZE];
Insertion involves hashing the key, then prepending or appending to the list at hashTable[index]. Search requires traversing the list until the matching key is found.