Search code examples
clinked-listhashtable

How to insert values into linked list members on an hashtable


I have a contact structure inserted into a linked list which is in an hashtable. I don't know if I defined all my structures correctly. I basically want to add a contact via input when given the command 'a' (command would be like this: a name mail phone). I sould not be able to add the contact if it already exists.

I've tried creating the necessary structure of an hashtable with linked lists, i just don't understand how to work with it. So this function would help me a lot with understanding this concept.

This is the structure i've tried

#define NOME_SIZE 1023
#define MAIL_SIZE 511
#define TELEFONE_SIZE 63
#define HASH_SIZE 1000

typedef struct contacts{
    char name[NOME_SIZE];
    char mail[MAIL_SIZE];
    char phone[TELEFONE_SIZE];
    struct contacts *next;
}HashList;


typedef struct hash_bucket{
    HashList *head, *tail; 
    int n_elements; 
}HashBucket;

HashBucket hashtable[HASH_SIZE]; 

I do not expect any output if i can successfuly add the contact. If it already exists it should return an error saying the contact already exists


Solution

  • A proposal from your code and my remarks. I removed n_elements because for me it is useless. I let tail but not sure it is useful because your list only have a next with a previous. I let arrays for name, phone and mail but I think it is better to use char *

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define NOME_SIZE 1023
    #define MAIL_SIZE 511
    #define TELEFONE_SIZE 63
    #define HASH_SIZE 1000
    
    typedef struct contacts{
        char name[NOME_SIZE];
        char mail[MAIL_SIZE];
        char phone[TELEFONE_SIZE];
        struct contacts *next;
    }HashList;
    
    
    typedef struct hash_bucket{
        HashList *head, *tail; 
        /* int n_elements; * I removed that field, it is useless */
    }HashBucket;
    
    HashBucket hashtable[HASH_SIZE]; 
    
    // from https://stackoverflow.com/a/7666577/2458991
    size_t hash(char * str)
    {
      size_t hash = 5381;
      unsigned char c;
    
      while ((c = (unsigned char) *str++) != 0)
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    
      return hash;
    }
    
    HashList * createElt(char * n, char * m, char * p)
    {
      HashList * e = malloc(sizeof(HashList));
    
      strncpy(e->name, n, NOME_SIZE - 1);
      e->name[NOME_SIZE - 1] = 0;
    
      strncpy(e->mail, m, MAIL_SIZE - 1);
      e->name[MAIL_SIZE - 1] = 0;
    
      strncpy(e->phone, p, TELEFONE_SIZE - 1);
      e->name[TELEFONE_SIZE - 1] = 0;
    
      e->next = NULL;
    
      return e;
    }
    
    // add or replace an element, the key is the name
    // return 0 if the entry is added, else a non null value if the entry is (probably) modified
    int insertElt(char * n, char * m, char * p)
    {
      // suppose list sort on the name
      HashBucket * hb = &hashtable[hash(n) % HASH_SIZE];
      HashList ** hl = &hb->head;
    
      for (;;) {
        if (*hl == NULL) {
          /* last (and may be first) element */
          *hl = createElt(n, m, p);
          hb->tail = *hl;
          return 0;
        }
    
        int cmp = strcmp((*hl)->name, n);
    
        if (cmp == 0) {
          /* replace */
          strncpy((*hl)->mail, m, MAIL_SIZE - 1);
          (*hl)->name[MAIL_SIZE - 1] = 0;
    
          strncpy((*hl)->phone, p, TELEFONE_SIZE - 1);
          (*hl)->name[TELEFONE_SIZE - 1] = 0;
    
          return 1;
        }
    
        if (cmp > 0) {
          /* insert before */
          HashList * e = createElt(n, m, p);
    
          e->next = *hl;
          *hl = e;
    
          return 0;
        }
    
        hl = &(*hl)->next;
      }
    }
    
    void pr()
    {
      for (size_t i = 0; i != HASH_SIZE; ++i)
        for (HashList * hl = hashtable[i].head; hl != NULL; hl = hl->next)
          printf("%s %s %s\n", hl->name, hl->mail, hl->phone);
    }
    
    int main()
    {
      printf("%d\n", insertElt("n1", "m1", "p1"));
      printf("%d\n", insertElt("n2", "m2", "p2"));
      pr();
      printf("%d\n", insertElt("n1", "mm1", "pp1"));
      pr();
    
      return 0;
    }
    

    Compilation and execution :

    pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall hm.c
    pi@raspberrypi:/tmp $ ./a.out
    0
    0
    n1 m1 p1
    n2 m2 p2
    1
    n1 mm1 pp1
    n2 m2 p2