Advertisement
Guest User

Hashing

a guest
Mar 26th, 2021
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.14 KB | None | 0 0
  1. #include <assert.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5.  
  6. #define NAAMLENGTH 10
  7.  
  8. typedef struct {
  9.   char naam[NAAMLENGTH];
  10. } Key;
  11.  
  12. typedef struct {
  13.   int nummer;
  14. } Waarde;
  15.  
  16. void printKeyWaarde(Key k, Waarde w) { printf("%s %d", k.naam, w.nummer); }
  17.  
  18. unsigned int hash(Key k) {
  19.   // gebaseerd op http://www.cse.yorku.ca/~oz/hash.html
  20.   unsigned char* s = k.naam;
  21.   unsigned int hash = 5381; // priemgetal
  22.   while (*s) {
  23.     hash = ((hash << 5) + hash) + *s++; /* hash * 33 + karakter */
  24.   }
  25.   return hash;
  26. }
  27.  
  28. int equals(Key k1, Key k2) { return strcmp(k1.naam, k2.naam) == 0; }
  29.  
  30. typedef struct elem {
  31.   Key key;
  32.   Waarde waarde;
  33.   struct elem* volgende;
  34. } Element;
  35.  
  36. Element* createEl(Key k, Waarde w) {
  37.   Element* el = malloc(sizeof(Element));
  38.   el->key = k;
  39.   el->waarde = w;
  40.   el->volgende = NULL;
  41.   return el;
  42. }
  43.  
  44. void destroyEl(Element* el) {
  45.   if (el != NULL) {
  46.     destroyEl(el->volgende);
  47.     free(el);
  48.   }
  49. }
  50.  
  51. typedef struct {
  52.   int lengte;
  53.   int gevuld;
  54.   Element** elementen;
  55. } HashTabel;
  56.  
  57. HashTabel create() {
  58.   HashTabel t = {0, 0, NULL};
  59.   return t;
  60. }
  61.  
  62. void destroy(HashTabel* t) {
  63.   if (t->lengte > 0) {
  64.     assert(t->elementen != NULL);
  65.     for (int i = 0; i < t->lengte; ++i) {
  66.       destroyEl(t->elementen[i]);
  67.     }
  68.     free(t->elementen);
  69.     t->elementen = NULL;
  70.     t->lengte = 0;
  71.     t->gevuld = 0;
  72.   }
  73. }
  74.  
  75. void print(HashTabel* t) {
  76.   printf("lengte %d gevuld %d\n", t->lengte, t->gevuld);
  77.   for (int i = 0; i < t->lengte; ++i) {
  78.     printf("index %3d", i);
  79.     Element* el = t->elementen[i];
  80.     while (el != NULL) {
  81.       printf(" | ");
  82.       printKeyWaarde(el->key, el->waarde);
  83.       el = el->volgende;
  84.     }
  85.     printf("\n");
  86.   }
  87. }
  88.  
  89. Element* vind(HashTabel* t, Key k) {
  90.   if (t->lengte == 0) {
  91.     return NULL;
  92.   }
  93.   int index = hash(k) % t->lengte;
  94.   Element* el = t->elementen[index];
  95.   while (el != NULL) {
  96.     if (equals(el->key, k)) {
  97.       return el;
  98.     }
  99.     el = el->volgende;
  100.   }
  101.   return NULL;
  102. }
  103.  
  104. void groei(HashTabel* t);
  105.  
  106. void voegToe(HashTabel* t, Key k, Waarde w) {
  107.   if (t->lengte == 0) {
  108.     groei(t);
  109.   }
  110.   int index = hash(k) % t->lengte;
  111.   Element* el = t->elementen[index];
  112.   if (el == NULL) {
  113.     t->elementen[index] = createEl(k, w);
  114.   } else if (equals(el->key, k)) {
  115.     return; // zit al in tabel
  116.   } else {
  117.     while (el->volgende != NULL) {
  118.       el = el->volgende;
  119.       if (equals(el->key, k)) {
  120.         return; // zit al in tabel
  121.       }
  122.     }
  123.     el->volgende = createEl(k, w);
  124.   }
  125.   t->gevuld += 1;
  126.   if (t->lengte <= t->gevuld) {
  127.     groei(t);
  128.   }
  129. }
  130.  
  131. void groei(HashTabel* t) {
  132.   HashTabel nieuw = create();
  133.   nieuw.lengte = 2 * t->lengte + 1; // 0,1,3,7,15, enz.
  134.   nieuw.elementen = malloc(sizeof(Element*) * nieuw.lengte);
  135.   for (int i = 0; i < nieuw.lengte; ++i) {
  136.     nieuw.elementen[i] = NULL;
  137.   }
  138.   for (int i = 0; i < t->lengte; ++i) {
  139.     Element* el = t->elementen[i];
  140.     while (el != NULL) {
  141.       voegToe(&nieuw, el->key, el->waarde);
  142.       el = el->volgende;
  143.     }
  144.   }
  145.   destroy(t);
  146.   t->lengte = nieuw.lengte;
  147.   t->gevuld = nieuw.gevuld;
  148.   t->elementen = nieuw.elementen;
  149. }
  150.  
  151. int verwijder(HashTabel* t, Key k) {
  152.   if (t->lengte == 0) {
  153.     return 0;
  154.   }
  155.   int index = hash(k) % t->lengte;
  156.   Element* el = t->elementen[index];
  157.   if (el == NULL) {
  158.     return 0;
  159.   }
  160.   if (equals(el->key, k)) {
  161.     Element* tmp = el->volgende;
  162.     free(el);
  163.     t->elementen[index] = tmp;
  164.     return 1;
  165.   }
  166.   while (el->volgende != NULL) {
  167.     if (equals(el->volgende->key, k)) {
  168.       Element* tmp = el->volgende->volgende;
  169.       free(el->volgende);
  170.       el->volgende = tmp;
  171.       t->gevuld -= 1;
  172.       return 1;
  173.     }
  174.     el = el->volgende;
  175.   }
  176.   return 0;
  177. }
  178.  
  179. void main() {
  180.   HashTabel t = create();
  181.   for (char i = 'a'; i < 'a' + 6; ++i) {
  182.     Waarde w = {i % 5};
  183.     Key k = {""};
  184.     for (int j = 0; j < NAAMLENGTH - 1; ++j) {
  185.       k.naam[j] = i + ((i+2*j) % 5); // gekozen om veel collisions te hebben
  186.     }
  187.     k.naam[NAAMLENGTH - 1] = '\0';
  188.     voegToe(&t, k, w);
  189.     print(&t);
  190.   }
  191.   Key k = {"gdfcegdfc"};
  192.   verwijder(&t, k);
  193.   print(&t);
  194.   destroy(&t);
  195. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement