ccousas

estruturas de datos e algoritmos en C
Log | Files | Refs

hash_table.c (4834B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 
      5 #define TABLE_SIZE 5
      6 
      7 typedef struct ENTRY {
      8     char* key;
      9     char* value;
     10     struct ENTRY* sig;
     11 } ENTRY_T;
     12 
     13 typedef struct {
     14     ENTRY_T** entries;
     15 } HTABLE_T;
     16 
     17 
     18 
     19 HTABLE_T* htable_init() {
     20     HTABLE_T* hashtable = malloc(sizeof(HTABLE_T)); // Allocate HashTable
     21     hashtable->entries = calloc(TABLE_SIZE, sizeof(ENTRY_T)); // Allocate entries
     22 
     23     // Set each entry to NULL (needed for proper operation)
     24     for (int i = 0; i < TABLE_SIZE; i++) {
     25         hashtable->entries[i] = NULL;
     26     }
     27 
     28     return hashtable;
     29 }
     30 
     31 
     32 
     33 unsigned int hash(const char* key) {
     34     unsigned long int value = 0;
     35 
     36     for (unsigned int i = 0; i < strlen(key); i++){
     37         value = value * 37 + key[i];
     38     }
     39     value = value % TABLE_SIZE;
     40     return value;
     41 }
     42 
     43 
     44 
     45 // Inicializa un nodo entry
     46 ENTRY_T* htable_pair(const char* key, const char* value){
     47     // Allocate the entry
     48     ENTRY_T* entry = malloc(sizeof(entry));
     49     entry->key = malloc(strlen(key)+1); // +1 polo NULL TERMINATOR '\0'
     50     entry->value = malloc(strlen(value) + 1);
     51 
     52     // Copy the key and value in place
     53     strcpy(entry->key, key);
     54     strcpy(entry->value, value);
     55 
     56     // sig (seguinte) starts out NULL but may be set later on
     57     entry->sig = NULL;
     58     return entry;
     59 }
     60 
     61 
     62 void htable_set (HTABLE_T* hashtable, const char* key, const char* value) {
     63     unsigned int slot = hash(key);
     64     ENTRY_T* entry = hashtable->entries[slot];
     65 
     66     if (entry == NULL) {
     67         hashtable->entries[slot] = htable_pair(key, value);
     68         return;
     69     }
     70 
     71     // Mira se estas intentando introducir unha clave que xa tes no hashTable para actualizala
     72     ENTRY_T* prev;
     73     while (entry != NULL) {
     74         // Comproba
     75         if (!strcmp(entry->key, key)) {
     76             // Update value
     77             free(entry->value);
     78             entry->value = malloc(strlen(value) + 1);
     79             strcpy(entry->value, value);
     80             return;
     81         }
     82 
     83         // walk to next
     84         prev = entry;
     85         entry = prev->sig;
     86     }
     87 
     88     // End of node list reached -> add new element
     89     prev->sig = htable_pair(key, value);
     90 }
     91 
     92 
     93 // Devolve NULL senon existe
     94 char* htable_get(HTABLE_T* hashtable, const char* key) {
     95     unsigned int slot = hash(key);
     96 
     97     // Try to find a valid slot
     98     ENTRY_T* entry = hashtable->entries[slot];
     99 
    100     // No slot means no entry
    101     if (entry == NULL) return NULL;
    102 
    103     // Walk through each entry in the slot, which could just be a single thing
    104     while (entry != NULL) {
    105         // Return a value if found
    106         if (!strcmp(entry->key, key) == 0) {
    107             return entry->value;
    108         }
    109 
    110         // Proceed to next key if available
    111         entry = entry->sig;
    112     }
    113 
    114     // Reaching here means there were >= 1 entries but no key match
    115     return NULL;
    116 }
    117 
    118 
    119 void htable_remove(HTABLE_T* hashtable, const char* key) {
    120     unsigned int slot = hash(key);
    121     // Try to find a valid slot
    122     ENTRY_T* entry = hashtable->entries[slot];
    123     ENTRY_T** tmp = &(hashtable->entries[slot]);
    124     if (entry == NULL) return;
    125 
    126     // Se esta na cabeza e ten sig deixas o sig a cabeza
    127     // Senon ten sig borraslle a cabeza
    128     if (!strcmp(entry->key, key)) {
    129         if (entry->sig == NULL) {
    130             hashtable->entries[slot] = NULL;
    131             free(entry);
    132         }
    133         else {
    134             hashtable->entries[slot] = entry->sig;
    135             free(entry);
    136         }
    137     }
    138     else {
    139         ENTRY_T* aux;
    140         while (*tmp != NULL) {
    141             if (!strcmp((*tmp)->key, key)) {
    142                 // Borrar a entry
    143                 aux = *tmp;
    144                 *tmp = (*tmp)->sig;
    145                 return;
    146             }
    147             tmp = &((*tmp)->sig);
    148         }
    149     }
    150     return;
    151 }
    152 
    153 
    154 void htable_print(HTABLE_T* hashtable) {
    155     for (int i = 0; i < TABLE_SIZE; i++) {
    156         ENTRY_T* entry = hashtable->entries[i];
    157 
    158         if (entry == NULL) continue;
    159 
    160         printf("slot[%4d]: ", i);
    161         for(;;) {
    162             printf("%s=%s ", entry->key, entry->value);
    163 
    164             if(entry->sig == NULL) break;
    165             entry = entry->sig;
    166         }
    167 
    168         printf("\n");
    169     }
    170 }
    171 
    172 
    173 
    174 int main() {
    175     HTABLE_T* ht = htable_init();
    176 
    177     htable_set(ht, "name1", "em");
    178     htable_set(ht, "name2", "russian");
    179     htable_set(ht, "name3", "pizza");
    180     htable_set(ht, "name4", "doge");
    181     htable_set(ht, "name5", "pyro");
    182     htable_set(ht, "name6", "joost");
    183     htable_set(ht, "name7", "kalix");
    184     htable_set(ht, "name8", "lemon");
    185     htable_set(ht, "name9", "lollipop");
    186     htable_set(ht, "name10", "oreo");
    187     htable_set(ht, "name11", "apache");
    188     htable_set(ht, "name12", "fanta");
    189     htable_set(ht, "name13", "kake");
    190     htable_set(ht, "name14", "tuna");
    191     htable_set(ht, "name15", "presunto");
    192 
    193     htable_remove(ht, "name7");
    194     htable_remove(ht, "name2");
    195 
    196     htable_print(ht);
    197     return 0;
    198 }