C Program To Implement Dictionary Using Hashing Algorithms Site

Abstract

A dictionary is a data structure that stores a collection of key-value pairs, where each key is unique and maps to a specific value. In this paper, we implement a dictionary using hashing algorithms in C programming language. We use a hash function to map keys to indices of a hash table, which stores the key-value pairs. The goal of this implementation is to provide efficient insertion, search, and deletion operations. We discuss the design and implementation of the dictionary using hashing algorithms and present the C code for the same.

Introduction

A dictionary, also known as a hash table or a map, is a fundamental data structure in computer science that stores a collection of key-value pairs. It allows for efficient retrieval of values by their associated keys. Hashing algorithms are widely used to implement dictionaries, as they provide fast lookup, insertion, and deletion operations.

Hashing Algorithms

Hashing algorithms are used to map keys to indices of a hash table. A hash function takes a key as input and generates a hash code, which is an integer that represents the index of the hash table where the corresponding value is stored. A good hash function should have the following properties:

  1. Deterministic: Given a key, the hash function should always generate the same hash code.
  2. Non-injective: Different keys should map to different hash codes.
  3. Fixed output size: The hash function should generate a fixed-size hash code.

Design and Implementation

Our implementation of the dictionary using hashing algorithms consists of the following components:

  1. Hash Table: A hash table is an array of structures, where each structure represents a key-value pair.
  2. Hash Function: We use a simple hash function that calculates the hash code by taking the modulus of the key with the size of the hash table.
  3. Insertion: When a new key-value pair is inserted, we calculate the hash code using the hash function and store the pair at the corresponding index of the hash table. If there is a collision (i.e., two keys map to the same index), we use chaining to store the colliding pairs.
  4. Search: When searching for a value by its key, we calculate the hash code using the hash function and retrieve the value from the corresponding index of the hash table.
  5. Deletion: When deleting a key-value pair, we calculate the hash code using the hash function and remove the pair from the corresponding index of the hash table.

C Code

Here is the C code for the dictionary implementation using hashing algorithms:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HASH_TABLE_SIZE 10
typedef struct Node 
    char* key;
    char* value;
    struct Node* next;
 Node;
typedef struct HashTable 
    Node** buckets;
    int size;
 HashTable;
// Hash function
int hash(char* key) 
    int hashCode = 0;
    for (int i = 0; i < strlen(key); i++) 
        hashCode += key[i];
return hashCode % HASH_TABLE_SIZE;
// Create a new node
Node* createNode(char* key, char* value) 
    Node* node = (Node*) malloc(sizeof(Node));
    node->key = (char*) malloc(strlen(key) + 1);
    strcpy(node->key, key);
    node->value = (char*) malloc(strlen(value) + 1);
    strcpy(node->value, value);
    node->next = NULL;
    return node;
// Create a new hash table
HashTable* createHashTable() 
    HashTable* hashTable = (HashTable*) malloc(sizeof(HashTable));
    hashTable->buckets = (Node**) malloc(sizeof(Node*) * HASH_TABLE_SIZE);
    hashTable->size = HASH_TABLE_SIZE;
    for (int i = 0; i < HASH_TABLE_SIZE; i++) 
        hashTable->buckets[i] = NULL;
return hashTable;
// Insert a key-value pair into the hash table
void insert(HashTable* hashTable, char* key, char* value) 
    int index = hash(key);
    Node* node = createNode(key, value);
    if (hashTable->buckets[index] == NULL) 
        hashTable->buckets[index] = node;
     else 
        Node* current = hashTable->buckets[index];
        while (current->next != NULL) 
            current = current->next;
current->next = node;
// Search for a value by its key
char* search(HashTable* hashTable, char* key) 
    int index = hash(key);
    Node* current = hashTable->buckets[index];
    while (current != NULL) 
        if (strcmp(current->key, key) == 0) 
            return current->value;
current = current->next;
return NULL;
// Delete a key-value pair from the hash table
void delete(HashTable* hashTable, char* key) 
    int index = hash(key);
    Node* current = hashTable->buckets[index];
    if (current == NULL) return;
    if (strcmp(current->key, key) == 0) 
        hashTable->buckets[index] = current->next;
        free(current->key);
        free(current->value);
        free(current);
     else 
        Node* previous = current;
        current = current->next;
        while (current != NULL) 
            if (strcmp(current->key, key) == 0) 
                previous->next = current->next;
                free(current->key);
                free(current->value);
                free(current);
                return;
previous = current;
            current = current->next;
// Print the hash table
void printHashTable(HashTable* hashTable) 
    for (int i = 0; i < HASH_TABLE_SIZE; i++) 
        Node* current = hashTable->buckets[i];
        printf("Bucket %d: ", i);
        while (current != NULL) 
            printf("%s -> %s, ", current->key, current->value);
            current = current->next;
printf("\n");
int main() 
    HashTable* hashTable = createHashTable();
    insert(hashTable, "apple", "fruit");
    insert(hashTable, "banana", "fruit");
    insert(hashTable, "carrot", "vegetable");
    printHashTable(hashTable);
    char* value = search(hashTable, "banana");
    printf("Value for key 'banana': %s\n", value);
    delete(hashTable, "apple");
    printHashTable(hashTable);
    return 0;

Conclusion

In this paper, we implemented a dictionary using hashing algorithms in C programming language. We discussed the design and implementation of the dictionary, including the hash function, insertion, search, and deletion operations. The C code provided demonstrates the implementation of the dictionary using hashing algorithms. This implementation provides efficient insertion, search, and deletion operations, making it suitable for a wide range of applications. c program to implement dictionary using hashing algorithms

References

To implement a dictionary in C using hashing, you must map string keys to values through a hash function and handle potential "collisions" where two keys produce the same hash . The most common approach for C dictionaries is Separate Chaining

, which uses an array of linked lists to store multiple entries at the same index. 1. Define Data Structures

A dictionary entry needs to store a key, its associated value, and a pointer to the next entry in case of a collision. Stack Overflow TABLE_SIZE Entry *next; } Entry;

Entry *hash_table[TABLE_SIZE]; Use code with caution. Copied to clipboard 2. Implement the Hash Function

A reliable hash function distributes keys uniformly across the table. The

algorithm is a popular choice for strings because it is simple and efficient. ((c = *str++)) hash = ((hash << ) + hash) + c; // hash * 33 + c hash % TABLE_SIZE; } Use code with caution. Copied to clipboard 3. Implement Core Operations

Dictionary operations include inserting new pairs, searching for keys, and deleting entries. Insert (and Update)

function calculates the hash, checks if the key already exists to update it, or adds a new node to the front of the linked list if it doesn't. Stack Overflow index = hash(key); Entry *temp = hash_table[index]; // Check if key already exists to update value (temp != NULL) (strcmp(temp->key, key) ==

) free(temp->value); temp->value = strdup(value); ; temp = temp->next; // Key not found, create new entry Entry *new_entry = malloc( Abstract A dictionary is a data structure that

(Entry)); new_entry->key = strdup(key); new_entry->value = strdup(value); new_entry->next = hash_table[index]; hash_table[index] = new_entry; } Use code with caution. Copied to clipboard

function retrieves the value associated with a key by traversing the list at the hashed index. Stack Overflow index = hash(key); Entry *temp = hash_table[index]; (temp != NULL) (strcmp(temp->key, key) == temp->value; temp = temp->next; // Not found Use code with caution. Copied to clipboard 4. Comparison of Collision Strategies While Separate Chaining is flexible, another method is Linear Probing

, where collisions are resolved by moving to the next open slot in the array. How to implement a hash table (in C) - Ben Hoyt

dictionary is an abstract data type that maps unique keys to values. Since C lacks a built-in dictionary like Python or C#, you can implement one efficiently using a hash table . This approach provides average constant-time complexity, , for insertion, search, and deletion. 1. Define the Data Structures

A dictionary requires a structure for individual entries (key-value pairs) and a structure for the table itself. To handle collisions—when two different keys produce the same hash—we use Separate Chaining

, where each table index points to a linked list of entries. GeeksforGeeks TABLE_SIZE

// 1. Structure for a single dictionary entry (node in linked list) Entry *next; } Entry; // 2. Structure for the Dictionary (Hash Table) Entry *buckets[TABLE_SIZE]; Dictionary; Use code with caution. Copied to clipboard 2. Implement the Hash Function

The hash function converts a string key into an integer index within the table's bounds. A common and effective algorithm for strings is

, which uses bit-shifting and a prime number (33) to minimize collisions. Stack Overflow hash_val = ((c = *key++)) hash_val = ((hash_val << ) + hash_val) + c; // hash * 33 + c hash_val % TABLE_SIZE; Use code with caution. Copied to clipboard 3. Core Dictionary Operations

These functions manage the lifecycle of entries in the dictionary: Stack Overflow

3.4 Delete Function

Deletion requires careful pointer management. Deterministic : Given a key, the hash function

int delete_key(Dictionary *dict, const char *key) 
    unsigned long hash = dict->hash_func(key);
    unsigned long index = hash % dict->size;
Entry *curr = dict->buckets[index];
Entry *prev = NULL;
while (curr) 
    if (strcmp(curr->key, key) == 0) 
        if (prev) 
            prev->next = curr->next;
         else 
            dict->buckets[index] = curr->next;
free(curr->key);
        free(curr->value);
        free(curr);
        dict->count--;
        return 1; // Success
prev = curr;
    curr = curr->next;
return 0; // Key not found

Step 5: Performance Analysis

Let's analyze the time complexities:

| Operation | Average Case | Worst Case (All Collisions) | |-----------|-------------|-------------------------------| | Insert | O(1) | O(n) | | Search | O(1) | O(n) | | Delete | O(1) | O(n) | | Resize | O(n) amortized | O(n) |

The worst case occurs when all keys hash to the same bucket.

C Program to Implement a Dictionary Using Hashing Algorithms

Step 3: Implementation of Core Functions

Let’s write each function systematically.

3.2 Insert Function

We need to handle:

void insert(Dictionary *dict, const char *key, const char *value) 
    unsigned long hash = dict->hash_func(key);
    unsigned long index = hash % dict->size;
// Check if key already exists
Entry *curr = dict->buckets[index];
while (curr) 
    if (strcmp(curr->key, key) == 0) 
        // Update existing value
        free(curr->value);
        curr->value = strdup(value);
        return;
curr = curr->next;
// Create new entry
Entry *new_entry = (Entry*)malloc(sizeof(Entry));
new_entry->key = strdup(key);
new_entry->value = strdup(value);
new_entry->next = dict->buckets[index];
dict->buckets[index] = new_entry;
dict->count++;
// Check load factor and resize if needed
if ((float)dict->count / dict->size > LOAD_FACTOR_THRESHOLD) 
    resize_dictionary(dict);

Delete a key

int delete_key(Dictionary* dict, const char* key) 
    int index = hash(key, dict->size);
    Entry* curr = dict->buckets[index];
    Entry* prev = NULL;
while (curr != NULL) 
    if (strcmp(curr->key, key) == 0) 
        if (prev == NULL) 
            // deleting head of chain
            dict->buckets[index] = curr->next;
         else 
            prev->next = curr->next;
free(curr->key);
        free(curr);
        dict->count--;
        return 1; // success
prev = curr;
    curr = curr->next;
return 0; // key not found