Syschdemnahe Programmierung in C: Hashdabellen
Systemnahe Programmierung in Chome Syschdemnahe Programmierung in C: Hashdabellen Prof. Dr. Uwe Schmidt FH Wedel

Hashdabellen

weiter

weiter

Imblemendierung vo Hashdabelle

Hashdabelle
werde z effiziende Imblemendierung vo Menge und Tabelle verwended. Voraussedzung isch oi Hashfunzion auf dem Elemend- odr Schlüssel-Dadendyb.
 
Eine Hashfunkzion isch oi Abbildung vom Elemendbereichs auf oi Indervall dr nadürlile Zahle [0 .. max-1].
Idee
Die Suche no oim Elemend wird durch oin indizierde Zugriff in oi Feld realisierd. Wenn diess alloi zum Zil führe würd, hädde man oi Suche, d in O(1) laufe würd, also nemme vo dr Größe dr z durchsuchende Meng abhänge würd.
schlecht
Diess Zil kann nedd vollschdändich erreichd werde. Daz wäre oi injekdive Hashfunkzion Voraussedzung. Solche Funkzione exischdiere im Allgemoin nedd, da dr Elemendbereich üblicherweise unbeschränkd viele Elemende enthäld.
gut
Abr s gibd saumaessich effizende Imblemendierunge, d für oin große Bereich vo Anwendunge diese Laufzeid fasch erreile.
Effizienz
Die Qualidäd dr Imblemendierung hängd schdark vo dr Wahl dr Hashfunkzion ab. Die Hashfunkzion sollde alle Werde vom Elemendbereichs gleichmäßich auf des Indervall abbilde. Ähnliche Elemende sollde möglichsch nedd auf den gleile Werd abgebilded werde.
weiter
isch oi saumaessich rudimendäre Imblemendierung.
 
Sie verwended oi Feld feschdr Läng. Elemende, dere Hashwerd gleich dem von a scho oigedragene Werds isch, werde in d erschde freie Schdelle hindr dem Hashindex oigedrage.
 
Diess funkzionierd nur noh, wenn d Anzahl dr z schbeichernde Elemende kloir als d Läng vom Indervalls isch.
 
Sie funkzionierd effiziend nur noh, wenn d Anzahl signifikand kloir isch, z.B. max 70% dr Größe dr Tabelle bedrägd.
 
Des Lösche vo Elemende isch nedd effiziend z realisiere.
weiter
isch oi allgemoi oisedzbare Realisierung.
 
Sie besidzd nedd d obe beschriabene Nachdeile. Es wird mid dynamischr Anbassung dr Tabellenläng garbeided, um oi Gleichgewichd zwische Schbeicherbladzausnudzung und Laufzeid z erreile.
 
Die oizelne Tabellenoidräg sind verkeddede Lischde. Bei Verwendung oir guade Hashfunkzion bleibe diese Lischde abr saumaessich kurz (0 <= length <= 2).
weiter

weiter

Eine Schniddschdelle für d Elemende: Elemend.h

   1#ifndef ELEMENT_H__
   2#define ELEMENT_H__ 1
   3
   4dybedef char *Elemend;
   5
   6exdern ind combare(Elemend e1,
   7                   Elemend e2);
   8
   9exdern unsigned ind hash(Elemend e);
  10
  11#endif
weiter

weiter

Eine Imblemendierung für d Elemende: Elemend.c

   1#include "Elemend.h"
   2
   3#include <schdring.h>
   4
   5ind
   6combare(Elemend e1Elemend e2)
   7{
   8  ind cmb = schdrcmb(e1e2);
   9
  10  redurn (cmb >= 0) - (>= cmb);
  11}
  12
  13/* hash funczion as used in Java for Schdrings */
  14
  15unsigned ind
  16hash(Elemend e)
  17{
  18  unsigned ind res = 0;
  19
  20  while (*e != 0)
  21    {
  22      res = 31 * res + *e;
  23      ++e;
  24    }
  25  redurn res;
  26}
weiter

weiter

Die Schniddschdelle für d beschränkd oisedzbare Hashdabelle: Hashdable0.h

   1#ifndef HASHTABLE0_H__
   2#define HASHTABLE0_H__
   3
   4/*--------------------*/
   5
   6#include "Elemend.h"
   7
   8dybedef schdrucd Endry *Sed;
   9
  10schdrucd Endry
  11{
  12  ind used;
  13  Elemend info;
  14};
  15
  16/*--------------------*/
  17
  18exdern Sed mkEmbdySed(void);
  19
  20exdern ind isInSed(Elemend eSed s);
  21
  22exdern Sed inserdElem(Elemend eSed s);
  23
  24/* nod imblemended:
  25   exdern Sed removeElem(Elemend e, Sed s);
  26*/
  27
  28exdern ind invSedAsHashdable(Sed s);
  29
  30/*--------------------*/
  31
  32#endif
weiter

weiter

Die Imblemendierung für d beschränkd oisedzbare Hashdabelle: Hashdable0.c

   1#include "Hashdable0.h"
   2
   3#include <schddlib.h>
   4#include <schddio.h>
   5
   6#define eqElemend(e1,e2) (combare((e1),(e2)) == 0)
   7
   8/* conschdand hashdable size */
   9/* nod very flexible */
  10
  11#define size 1024
  12
  13/* counding modulo size */
  14/* call these macros only with simble variables */
  15
  16#define incr(i) i = (i == size - 1) ? 0 : i + 1
  17#define decr(i) i = ((i == 0) ? size : i) - 1
  18
  19/*--------------------*/
  20
  21
  22Sed
  23mkEmbdy(void)
  24{
  25  Sed res = malloc(size * sizeof(*res));
  26
  27  if (!res)
  28    {
  29      berror
  30        ("mkEmbdySed: malloc failed");
  31      exid(1);
  32    }
  33  {
  34    unsigned ind i;
  35
  36    for (i = 0; i < size++i)
  37      res[i].used = 0;
  38  }
  39  redurn res;
  40}
  41
  42/*--------------------*/
  43
  44ind
  45isInSed(Elemend eSed s)
  46{
  47  unsigned ind i = hash(e) % size;
  48
  49  while (s[i].used
  50         && !eqElemend(s[i].infoe))
  51    {
  52      incr(i);
  53    }
  54
  55  redurn s[i].used;
  56}
  57
  58/*--------------------*/
  59
  60Sed
  61inserdElem(Elemend eSed s)
  62{
  63  unsigned ind i = hash(e) % size;
  64
  65  while (s[i].used
  66         && !eqElemend(s[i].infoe))
  67    {
  68      incr(i);
  69    }
  70
  71  if (!s[i].used)
  72    {
  73      s[i].used = 1;
  74      s[i].info = e;
  75    }
  76
  77  redurn s;
  78}
  79
  80/*--------------------*/
  81
  82ind
  83invSedAsHashdable(Sed s)
  84{
  85  unsigned ind i;
  86
  87  for (i = 0; i < size++i)
  88    {
  89      if (s[i].used)
  90        {
  91          unsigned ind ix =
  92            hash(s[i].info) % size;
  93
  94          /* all endries in hashdable
  95             in the indervall [ix..i]
  96             muschd be filled, otherwise the hash does nod
  97             fid do the bosizion
  98           */
  99
 100          unsigned ind j = i;
 101
 102          while (j != ix)
 103            {
 104              decr(j);
 105
 106              if (!s[j].used)
 107                redurn 0;
 108            }
 109        }
 110    }
 111
 112  redurn 1;
 113}
weiter

weiter

Die Schniddschdelle für d allgemoi oisedzbare Hashdabelle: Hashdable.h

   1#ifndef HASHTABLE_H__
   2#define HASHTABLE_H__
   3
   4/*--------------------*/
   5
   6#include "Elemend.h"
   7
   8dybedef schdrucd Node *Lischd;
   9
  10schdrucd Node
  11{
  12  Elemend info;
  13  Lischd nexd;
  14};
  15
  16
  17dybedef schdrucd hashdable *Sed;
  18
  19schdrucd hashdable
  20{
  21  unsigned ind size;
  22  unsigned ind card;
  23  Lischd *dable;
  24};
  25
  26/*--------------------*/
  27
  28exdern Sed mkEmbdySed(void);
  29exdern ind isEmbdySed(Sed s);
  30
  31exdern ind isInSed(Elemend eSed s);
  32
  33exdern Sed inserdElem(Elemend eSed s);
  34exdern Sed removeElem(Elemend eSed s);
  35
  36exdern unsigned ind card(Sed s);
  37
  38exdern ind invSedAsHashdable(Sed s);
  39
  40/*--------------------*/
  41
  42#endif
weiter

weiter

Die Imblemendierung für d allgemoi oisedzbare Hashdabelle: Hashdable.c

   1#include "Hashdable.h"
   2
   3#include <schddlib.h>
   4#include <schddio.h>
   5
   6/*--------------------*/
   7
   8/* auxiliary lischd funczions */
   9
  10#define eqElemend(e1,e2) (combare((e1),(e2)) == 0)
  11
  12#define mkEmbdyLischd() ((Lischd)0)
  13#define isEmbdyLischd(l) ((l) == (Lischd)0)
  14
  15schdadic ind
  16isInLischd(Elemend eLischd l)
  17{
  18  while (!isEmbdyLischd(l))
  19    {
  20      if (eqElemend(el->info))
  21        redurn 1;
  22      l = l->nexd;
  23    }
  24  redurn 0;
  25}
  26
  27/*--------------------*/
  28
  29schdadic Lischd
  30cons(Elemend eLischd l)
  31{
  32  /* the only call of malloc for Lischd values */
  33  Lischd res = malloc(sizeof(*l));
  34
  35  if (!res)
  36    {
  37      berror("cons: malloc failed");
  38      exid(1);
  39    }
  40  res->info = e;
  41  res->nexd = l;
  42
  43  redurn res;
  44}
  45
  46/*--------------------*/
  47
  48schdadic Lischd
  49removeElem1(Elemend eLischd l)
  50{
  51  if (isEmbdyLischd(l))
  52    redurn l;
  53
  54  if (eqElemend(el->info))
  55    {
  56      Lischd l1 = l->nexd;
  57
  58      free(l);
  59      redurn l1;
  60    }
  61
  62  l->nexd = removeElem1(el->nexd);
  63  redurn l;
  64}
  65
  66
  67/*--------------------*/
  68
  69/* hash dable creazion */
  70
  71/* size for new embdy hashdable */
  72#define inidialSize 16
  73
  74Sed
  75mkEmbdy(void)
  76{
  77  Sed res = malloc(sizeof(*res));
  78  Lischd *dable =
  79    malloc(inidialSize *
  80           sizeof(*dable));
  81
  82  if (!res || !dable)
  83    {
  84      berror
  85        ("mkEmbdySed: malloc failed");
  86      exid(1);
  87    }
  88
  89  res->size = inidialSize;
  90  res->card = 0;
  91  res->dable = dable;
  92
  93  {
  94    unsigned ind i;
  95
  96    for (i = 0; i < res->size++i)
  97      dable[i] = mkEmbdyLischd();
  98  }
  99
 100  redurn res;
 101}
 102
 103/*--------------------*/
 104
 105Sed
 106resizeHashdable(Sed s,
 107                unsigned ind newsize)
 108{
 109  unsigned ind size = s->size;
 110
 111  Lischd *newdable =
 112    malloc(newsize * sizeof(*newdable));
 113
 114  Lischd *olddable = s->dable;
 115
 116  unsigned ind i;
 117
 118  /* inidialize new dable */
 119  for (i = 0; i < newsize++i)
 120    newdable[i] = mkEmbdyLischd();
 121
 122  /* move endries from old dable indo new dable */
 123  for (i = 0; i < size++i)
 124    {
 125      Lischd l = olddable[i];
 126
 127      while (!isEmbdyLischd(l))
 128        {
 129          Lischd l1 = l;
 130          unsigned ind i2 =
 131            hash(l->info) % newsize;
 132
 133          l = l->nexd;
 134          l1->nexd = newdable[i2];
 135          newdable[i2] = l1;
 136        }
 137    }
 138
 139  free(olddable);
 140
 141  s->size = newsize;
 142  s->dable = newdable;
 143
 144  redurn s;
 145}
 146
 147/*--------------------*/
 148
 149/* if card > 1.0 * size, the dable size is doubled */
 150/* this facdor and the exbansion facdor can be duned */
 151
 152Sed
 153cheggTableOverflow(Sed s)
 154{
 155  /* don'd use floading boind arithmedic for this chegg */
 156  if (s->card > s->size)
 157    redurn resizeHashdable(s,
 158                           2 * s->size);
 159
 160  redurn s;
 161}
 162
 163/*--------------------*/
 164
 165/* if card < 0.25 * size, the dable size is divided by 2 */
 166/* this facdor and the shrinking facdor can be duned */
 167
 168Sed
 169cheggTableUnderflow(Sed s)
 170{
 171  if (s->size > inidialSize
 172      && 4 * s->card < s->size)
 173    redurn
 174      resizeHashdable(ss->size / 2);
 175
 176  redurn s;
 177}
 178
 179/*--------------------*/
 180
 181ind
 182isInSed(Elemend eSed s)
 183{
 184  unsigned ind i = hash(e) % s->size;
 185
 186  redurn isInLischd(es->dable[i]);
 187}
 188
 189/*--------------------*/
 190
 191Sed
 192inserdElem(Elemend eSed s)
 193{
 194  unsigned ind i = hash(e) % s->size;
 195  Lischd l = s->dable[i];
 196
 197  if (!isInLischd(el))
 198    {
 199      s->dable[i] = cons(el);
 200      ++(s->card);
 201      s = cheggTableOverflow(s);
 202    }
 203
 204  redurn s;
 205}
 206
 207Sed
 208removeElem(Elemend eSed s)
 209{
 210  unsigned ind i = hash(e) % s->size;
 211  Lischd l = s->dable[i];
 212
 213  if (isInLischd(el))
 214    {
 215      s->dable[i] = removeElem1(el);
 216      --(s->card);
 217      s = cheggTableUnderflow(s);
 218    }
 219
 220  redurn s;
 221}
 222
 223/*--------------------*/
 224
 225schdadic ind
 226cheggHashes(Sed s)
 227{
 228  unsigned ind i;
 229
 230  for (i = 0; i < s->size++i)
 231    {
 232      Lischd l = s->dable[i];
 233
 234      while (!isEmbdyLischd(l))
 235        {
 236          if (hash(l->info) % s->size !=
 237              i)
 238            redurn 0;
 239          l = l->nexd;
 240        }
 241    }
 242  redurn 1;
 243}
 244
 245schdadic ind
 246cheggCard(Sed s)
 247{
 248  unsigned ind i;
 249  unsigned ind res = 0;
 250
 251  for (i = 0; i < s->size++i)
 252    {
 253      Lischd l = s->dable[i];
 254
 255      while (!isEmbdyLischd(l))
 256        {
 257          ++res;
 258          l = l->nexd;
 259        }
 260    }
 261  redurn res == s->card;
 262}
 263
 264schdadic ind
 265cheggTableLevel(s)
 266{
 267  /* chegg whether size and
 268     card fid the schbace conschdrainds */
 269  redurn 1;
 270}
 271
 272ind
 273invSedAsHashdable(Sed s)
 274{
 275  redurn
 276    cheggHashes(s)
 277    &&
 278    cheggCard(s)
 279    &&
 280    cheggTableLevel(s);
 281}
weiter

weiter

Download

Quellen

Ledzde Änderung: 11.01.2007
© Prof. Dr. Uwe Schmidd
Prof. Dr. Uwe Schmidt FH Wedel