hash_table_l2


"/home/yossef/notes/git/projects/hash_table//hash_table_l2.md"

path: git/projects/hash_table//hash_table_l2.md

- **fileName**: hash_table_l2
- **Created on**: 2025-03-30 17:07:39

check the .h file for hash_table (hash_table.h)

// the file for allowing import the hash_table functions

/* the type of ht_item every item must have a key and value
{
"name": "ahmed",
}; */
typedef struct {
    char *key; // the key for the element that use to search and delete
    char *value; // the value for the key
} ht_item;

/* type for the object hash */
typedef struct {
    int size; //  size : the size for the object it's by the way a a dynmaic size
    int base_size; // base_size: starting size
    int count; // count: number of ittem for ht_item insert into object
    ht_item **items; // ht_item: it's pointer of the array of items
} ht_hash_table;

// ht_item: the main function for adding a ht_item(key: value) to hash table
ht_item *ht_new_item(const char *k, const char *v); 
// for deleting specifi ht_item(key: value) from hast table using a key of search
void ht_del_item(ht_item *i);
// return new hesh table 
ht_hash_table *ht_new();
// for delete and free the hash table
void ht_table_delete(ht_hash_table *ht);
// for hashing(why hashing)
static int ht_hash(const char *s, const int a, const int m);
static int ht_get_hash(const char *s, const int num_buckets, const int attempt);
void ht_insert(ht_hash_table *ht, const char *key, const char *value);
char *ht_search(ht_hash_table *ht, const char *key);
void ht_delete(ht_hash_table *ht, const char *key);
void ht_resize_increase(ht_hash_table* ht); 
static void ht_resize_decrease(ht_hash_table* ht);
void ht_print(ht_hash_table *ht);

starting with the main logic for (hash_table.c)

#include "hash_table.h" // for getting the export and import from hash_table.h
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "prime.h"

// global variables
#define HT_PRIME_1 151
#define HT_PRIME_2 163
#define HT_INITIAL_BASE_SIZE 6
static ht_item HT_DELETED_ITEM = {NULL, NULL};

/**
 * @brief init the item
 * @param k is the key value for the item
 * @param v is the value
 */
ht_item *ht_new_item(const char *k, const char *v) {
    ht_item *i = malloc(sizeof(ht_item));
    i->key = strdup(k);
    i->value = strdup(v);
    return i;
};

void ht_del_item(ht_item *i) {
        free(i->key);
        free(i->value);
        free(i);
};

/**
 * @brief delete an table
 * @param ht the hash table that want ot delete
 */
void ht_table_delete(ht_hash_table *ht) {
    for (size_t i = 0; i < ht->size; i++) {
        ht_item *item = ht->items[i];
        if (item != NULL && item != &HT_DELETED_ITEM) {
            ht_del_item(item);
        };
    };
    free(ht->items);
    free(ht);
};

/**
 *@brief the function for hash the table item key
 *@param s the item in table
 *@param a prime number larger than the size of the alphabet > 128
 *@param m is the number for num_buckets
 */
static int ht_hash(const char *s, const int a, const int m) {
    long hash = 0;
    const int len_s = strlen(s);
    for (int i = 0; i < len_s; i++) {
        hash += (long)pow(a, len_s - (i + 1)) * s[i];
        hash = hash % m;
    };
    return (int)hash;
};

/**
 *@brief the function for double hasing
 *@param s the item in table
 *@param num_buckets is the number for num_buckets
 *@param attempt is the number of attempt
 */
static int ht_get_hash(const char *s, const int num_buckets, const int attempt) {
    const int hash_a = ht_hash(s, HT_PRIME_1, num_buckets);
    const int hash_b = ht_hash(s, HT_PRIME_2, num_buckets);
    return (hash_a + (attempt * (hash_b + 1))) % num_buckets;
};

/**
 * @brief search the value of the key
 * @param ht the hash table
 * @param key the key that want to search
 * @return the value of the key
 */
void ht_insert(ht_hash_table *ht, const char *key, const char *value) {
    const int load = ht->count * 100 / ht->size;
    if (load > 70 ) {
        ht_resize_increase(ht); 
    }
    ht_item *item = ht_new_item(key, value);
    int index = ht_get_hash(item->key, ht->size, 0);
    ht_item *cur_item = ht->items[index];
    int i = 1;
    while (cur_item != NULL && cur_item != &HT_DELETED_ITEM) {
        index = ht_get_hash(item->key, ht->size, i);
        cur_item = ht->items[index];
        i++;
    };
    ht->items[index] = item;
    ht->count++;
};

/**
 * @brief search the value of the key
 * @param ht the hash table
 * @param key the key that want to search
 * @return the value of the key
 */
char *ht_search(ht_hash_table *ht, const char *key) {
    int index = ht_get_hash(key, ht->size, 0);
    ht_item *item = ht->items[index];
    int i = 1;
    while (item != NULL) {
        if (item != &HT_DELETED_ITEM)
            if (strcmp(item->key, key) == 0)
                return item->value;
        index = ht_get_hash(key, ht->size, i);
        item = ht->items[index];
        i++;
    };
    return NULL;
};

/**
 * @brief delete the value of the key
 * @param ht the hash table
 * @param key the key that want to delete
 */
void ht_delete(ht_hash_table *ht, const char *key) {
    const int load = ht->count * 100 / ht->size;
    if (load < 10)
        ht_resize_decrease(ht);
    int index = ht_get_hash(key, ht->size, 0);
    ht_item *item = ht->items[index];
    int i = 1;
    while (item != NULL) {
        if (item != &HT_DELETED_ITEM) {
            if (strcmp(item->key, key) == 0) {
                ht->items[index] = &HT_DELETED_ITEM;
                ht_del_item(item);
            };
        };
        index = ht_get_hash(key, ht->size, i);
        item = ht->items[index];
        i++;
    };
    ht->count--;
};

/**
  *@description the resize function for the hash
  *@param the new size for the hash table
 */
static ht_hash_table *ht_new_sized(const int base_size) {
    ht_hash_table *ht = malloc(sizeof(ht_hash_table));
    ht->base_size = base_size;
    ht->size = next_prime(ht->base_size);
    ht->count = 0;
    ht->items = calloc((size_t)ht->size, sizeof(ht_item *));
    return ht;
};

/**
  *@description for initalzation the size for hash table first time
  *@param HT_INITIAL_BASE_SIZE the inital value for the size for the hash table
 */
ht_hash_table* ht_new() {
    return ht_new_sized(HT_INITIAL_BASE_SIZE);
}

/**
 *@description for resize the hash table when there is overflow in the hash table
 *@param ht the hash table 
 *@param base_size the size for the new hash table
 */
static void ht_resize(ht_hash_table* ht, const int new_size) {

    ht_item **items = realloc(ht->items,new_size * sizeof(ht_item *));
    if (items == NULL) {
        puts("error in hte calloc size for new items for new size \n");
        return;
    }

    printf("-- the old size of the hash tiabel is: %d --\n", ht->size);
    ht->base_size = new_size;
    ht->size = new_size;
    ht->items = items;
    printf("-- success resize the hash table new size: %d --\n", ht->size);
}


/**
 *@description for resize the hash table when there is overflow in the hash table
 *@param ht the hash table 
 *@param base_size the size for the new hash table
 * HINT THIS FUNCITON IS NOT WORKING CORRECTLY PROBLEM IN THE RESIZE FUNCTION
 */
/*static void ht_resize(ht_hash_table* ht, const int base_size) {
    puts("wlcome from the reize function and yossef \n");
    ht_hash_table *new_ht = ht_new_sized(base_size);
    printf("the new size for hash table is: %d\n", new_ht->size);
    printf("the new base_size for hash table is: %d\n", new_ht->base_size);
    for (size_t i = 0; i < ht->size; i++) {
        ht_item* item =  ht->items[i];
        if (item != NULL && item != &HT_DELETED_ITEM 
                && item->key != NULL && item->value != NULL) {
            printf(" the key: %s, the value: %s \n", item->key, item->value);
            ht_insert(new_ht, item->key, item->value);
            puts("adding and element for the new_ht \n");
        }
    }

    ht->base_size = new_ht->base_size;
    ht->count = new_ht->count;

    const int tmp_size = ht->size;
    ht->size = new_ht->size;
    new_ht->base_size = tmp_size;

    ht_item** tmp_items = ht->items;
    ht->items = new_ht->items;
    new_ht->items = tmp_items;

    ht_table_delete(new_ht);
    puts("finsh resize the hash table \n");
};
*/

/**
  @description for the increase the size for hash table
  @param ht the hash table
 */
void ht_resize_increase(ht_hash_table* ht) {
    const int newSize = ht->base_size * 2;
    ht_resize(ht, newSize);
}

/**
  @description for the decrease the size for hash table
  @param ht the hash table
 */
static void ht_resize_decrease(ht_hash_table* ht) {
    const int newSize = ht->base_size / 2;
    ht_resize(ht, newSize);
}


/**
  @description for the print the hash table
  @param ht the hash table
 */
void ht_print(ht_hash_table *ht) {
    for (size_t i = 0; i < ht->size; i++) {
        ht_item *item = ht->items[i];
        if (item != NULL && item != &HT_DELETED_ITEM) {
            printf("==> the key: %s, the value: %s \n", item->key, item->value);
        }
    }
}

continue:[[]]
before:./hash_table_l1.md