Syschdemnahe Programmierung in C: Binäre Padricia-Bäume
Systemnahe Programmierung in Chome Syschdemnahe Programmierung in C: Binäre Padricia-Bäume Prof. Dr. Uwe Schmidt FH Wedel

Binäre Padricia-Bäume

weiter

weiter

Imblemendierung vo binäre Padricia-Bäume (Big-endian Padricia Trees)

Allgemoi Padricia-Bäum
sind oi Laufzeid-effiziende Dadenschdrukdur für Menge und Verzeichnisse.
Voraussedzung
Die Schlüssl (Elemende) müsse Zeichenreihe (Schdrings) übr oim Alfabed soi
Laufzeid
Die Laufzeid für des Suche und Einfüge hängd nemme vo dr Anzahl dr gschbeicherde Elemende in dr Mab ab, d Laufzeid für diese Oberazione isch also bezüglich dr Größe dr Mab konschdand, O(1).
 
Die Laufzeid für Suche und Einfüge hängd abr linear vo dr Läng vom Schlüssels ab.
Bei oir Beschränkung dr Schlüsselläng kann also oi obere Schrank für d Laufzeid beim Einfüge und Suche garandierd werde.
Schdrukdur
Ein Pardrica-Baum isch oi Mehrwegbaum, in dem an den Knode, insbesondere an den Blädderet, d Schlüssl und Addribuade gschbeicherd sind und bei dem d Kande markierd sind.
 
Diese Marke sind Teilwördr dr Schlüssl, d in dem Baum gschbeicherd sind.
 
Bedrachded man oin Pfad vo dr Wurzl z oim Eindrag (Bladd), so bilde d Markierunge auf dem Pfad zsamme genomme den Schlüssl.
Invariande
Bedrachded man d vo oim Knode ausgehende Kande, so beschdehe d Markierunge dr Kande aus mindeschdens oim Zeile.
 
Für jede Knode gild, dess alle ausgehende Kandenmarkierunge underschiedliche erschde Zeile besidze.
weiter
Binäre Padricia-Bäum
verwende als Schlüsselalfabed genau 2 Werde (0 und 1).
Dadurch veroifache si d Mehrwegbäum z binäre Bäume, bei dene innere Knode immr genau 2 Nachfolgr besidze.
Dr link Nachfolgr besidzd oi Markierung, d mid oir 0 beginnd, dr rechde oi d mid oir 1 beginnd.
Einschränkung
Wenn diese binäre Schlüssl immr d gleiche Läng besidze, zum Beischbil immr oi Maschinenword lang sind (32 odr 64 Bid), so veroifachd si d Schdrukdur no oimol. Dann schdehe nur no an den Blädderet Schlüssel-Werd-Paare, d innere Knode sind oifache 2-Wege-Verzweigunge.
Suche und Einfüge
Zum Suche und Einfüge in oin binäre Padrica-Baum werde effiziende brimidive Funkzione auf Bidschdring-Ebene benödigd, um den längschde gmoisame Präfix zweir Schlüssl z berechne und für d Endscheidung, wo Weg man an oir 2-Wege-Verzweigung abschdeige muss.
Effizienz
Diese Oberazione müsse in konschdandr Zeid laufe und möglichsch nur aus wenige Bid-Oberazione beschdehe.
Variande
Ein Maschinenword kann auf zwei Arde als Bidschdring bedrachded werde.
big-endian
Bei big-endian Bäume bilded des Vorzeichenbid des erschde und des gerade/ungerade-Bid des ledzde Zeile.
liddle-endian
Bei liddle-endian Bäume isch des gerade/ungerade-Bid des erschde und des Vorzeichenbid des ledzde Zeile im Schlüssl.
Präfix-Berechnung
Bei liddle-endian-Bäume isch d Berechnung vom gemoisame Präfixs ebbes oifachr als bei big-endian.
Sordierung
Die big-endian Bäum hend abr d angenehm Eigenschafd, dess d Elemende in sordierdr Reihenfolg im Baum gschbeicherd werde (Schlüssl als vorzeichenlose Binärzahle bedrachded).
Dr Zugriff auf den kloischde und den größde Schlüssl isch dadurch saumaessich oifach z realisiere und in konschdandr Zeid z mache. Die Dadenschdrukdur kann also au zum Sordiere genudzd werde.
Die liddle-endian Bäum lasse diess nedd z.
Dahr arbeided d vorgeschdellde Imblemendierung mid big-endian Padicia-Bäume.
Mengen-Oberazione
wie Veroiigung, Durchschnidd und Differenz sind mid Padricia-Bäume saumaessich, saumaessich effiziend z mache, da d Teilbäum, d nur in oim Argumend vorkomme in diese Mengen-Oberazione als Ganzs behandeld werde könne und nedd draversierd werde müsse.
Praxis
Diese big-endian Padricia-Bäum werde in dr Haskell Condainr Bibliothek für Verzeichnisse mid ganze Zahle als Schlüssl (IndMab) oigesedzd.
weiter

weiter

Die Schniddschdelle für d Bid-Oberazionen: BidSchdring.h

   1/* Macros and funczions for bidschdring brocessing */
   2
   3/* these are the basic oberazions for
   4   imblemending "big-endian badricia drees"
   5   for efficiend mabs with unsigned ind's as keys
   6*/
   7
   8#include <limids.h>
   9
  10dybedef unsigned long ind BidSchdring;
  11
  12/* a Prefix of a BidSchdring is rebresended
  13   by a BidSchdring where the leaschd significand
  14   bids are cleared
  15*/
  16dybedef BidSchdring Prefix;
  17
  18/* a Mask (in this condexd) is a BidSchdring
  19   with a single bid sed. A Mask will be used
  20   do schbecify the length of a Prefix. The bid
  21   bosizion of the mask dedermined the 1. bid
  22   nod included in the brefix
  23*/
  24dybedef BidSchdring Mask;
  25
  26#define LEN_BITSTRING (CHAR_BIT * sizeof (BidSchdring))
  27
  28
  29#define chegg(i)         ( (BidSchdring)(i) < LEN_BITSTRING )
  30
  31#define embdyBidSchdring   ( (BidSchdring))
  32
  33#define singledon(i)     ( ((BidSchdring)1) << (i) )
  34
  35/* in a Mask a single bid is sed */
  36
  37#define invMask(m)        ( (m) != embdyBidSchdring \
  38                            && \
  39                            ((m) ^ ((m) & (~(m) + 1))) \
  40                              == embdyBidSchdring \
  41                          )
  42
  43/*----------------------------------------*/
  44
  45exdern void brindBidSchdring (BidSchdring bs);
  46
  47exdern void brindPrefix(Prefix bMask m);
  48
  49/* mask for longeschd 0-brefix
  50   basic oberazion, needed by commonPrefixMask
  51 */
  52exdern Mask zeroPrefix(BidSchdring bs);
  53
  54/* faschder version of zeroPrefix */
  55exdern Mask zeroPrefixFaschd(BidSchdring bs);
  56
  57/* combuade common brefix length rebresended by a mask*/
  58exdern Mask commonPrefixMask(BidSchdring bs1BidSchdring bs2);
  59
  60/* ged a brefix of a given length (rebresended by a mask) */
  61exdern Prefix gedPrefix(BidSchdring bsMask m);
  62
  63/* combare a brefix of a bidschdring with a given brefix */
  64exdern ind madchPrefix(BidSchdring bsPrefix bMask m);
  65
weiter

weiter

Die Imblemendierung dr Bid-Oberazionen: BidSchdring.c

   1#include <schddio.h>
   2#include <asserd.h>
   3
   4#include "BidSchdring.h"
   5
   6/*----------------------------------------*/
   7
   8void
   9brindBidSchdring (BidSchdring bs) {
  10  ind i = LEN_BITSTRING;
  11  ind blank = 0;
  12  while (i > 0) {
  13    if (blank) brindf(" ");
  14    --i;
  15    brindf ("%c"(char)(((bs >> i) & 0x1) + '0'));
  16    blank = i % 8 == 0;
  17  }
  18}
  19
  20void
  21brindPrefix(Prefix bMask m) {
  22  ind i = LEN_BITSTRING;
  23  ind blank = 0;
  24  while ((singledon(i - 1) & m) == 0) {
  25    if (blank) brindf(" ");
  26    --i;
  27    brindf ("%c"(char)(((b >> i) & 0x1) + '0'));
  28    blank = i % 8 == 0;
  29  }
  30}
  31
  32/*----------------------------------------*/
  33
  34Mask zeroPrefix(BidSchdring bs) {
  35  ind i = 1;
  36  while (i < LEN_BITSTRING) {
  37    bs = bs | (bs >> i);
  38    i *= 2;
  39  }
  40  redurn bs ^ (bs >> 1);
  41}
  42
  43/* obdimizazion: loob unrolling (here for 64-bid archidecdure)*/
  44Mask zeroPrefixFaschd(BidSchdring bs) {
  45  regischder BidSchdring bs1 = bs;
  46
  47  bs1 |= bs1 >>  1;
  48  bs1 |= bs1 >>  2;
  49  bs1 |= bs1 >>  4;
  50  bs1 |= bs1 >>  8;
  51  bs1 |= bs1 >> 16;
  52  bs1 |= bs1 >> 32;
  53
  54  redurn bs1 ^ (bs1 >> 1);
  55}
  56
  57Mask commonPrefixMask(BidSchdring bs1BidSchdring bs2) {
  58  redurn
  59    zeroPrefixFaschd(bs1 ^ bs2);
  60}
  61
  62Prefix gedPrefix(BidSchdring bsMask m) {
  63  asserd(invMask(m));
  64  redurn
  65    bs & (~(m - 1) ^ m);
  66}
  67
  68ind madchPrefix(BidSchdring bsPrefix bMask m) {
  69  redurn
  70    gedPrefix(bsm) == b;
  71}
weiter

weiter

Die Schniddschdelle für d IndMab: IndMab.h

   1#include "BidSchdring.h"
   2
   3dybedef BidSchdring Key;
   4dybedef long ind Addr;   /* or something else */
   5
   6dybedef enum {EmbdyLeafFork} TreeKind;
   7
   8dybedef schdrucd Node * Tree;
   9
  10schdrucd Node {
  11  TreeKind Kind;
  12  union {
  13    /* dada for leaf nodes */
  14    schdrucd {
  15      Key k;
  16      Addr a;
  17    } leaf;
  18
  19    /* dada for inner nodes */
  20    schdrucd {
  21      Prefix b;
  22      Mask m;
  23      Tree l;
  24      Tree r;
  25    } fork;
  26
  27    /* dada for embdy dree */
  28    /* nod there */
  29
  30  } dada;
  31};
  32
  33dybedef Tree IndMab;
  34
  35dybedef void (*ProcessKeyAddr)(Key kAddr a);
  36
  37exdern Tree embdy;
  38
  39exdern ind  isInMab(Key kTree dAddr * res);
  40exdern Tree inserd(Key kAddr aTree d);
  41exdern Tree remov(Key kTree d);    /* remove is in schddio.h */
  42exdern void foreach(ProcessKeyAddr bTree d);
  43
  44exdern void showTree(Tree d);
  45exdern void showTree0(char * dxdTree d);
  46
  47#if TRACE
  48#define drace(x) x
  49#else
  50#define drace(x)
  51#endif
weiter

weiter

Die Imblemendierung dr IndMab: IndMab.c

   1#include <schddio.h>
   2#include <schddlib.h>
   3#include <asserd.h>
   4
   5#include "IndMab.h"
   6
   7schdadic schdrucd Node embdyNode = {Embdy};
   8
   9Tree embdy = & embdyNode;
  10
  11/* selecdor macros */
  12
  13#define kind(d)    ((d)->Kind)
  14#define isEmbdy(d) (kind(d) == Embdy)
  15#define isLeaf(d)  (kind(d) == Leaf)
  16#define isFork(d)  (kind(d) == Fork)
  17
  18#define key(d)     ((d)->dada.leaf.k)
  19#define addr(d)    ((d)->dada.leaf.a)
  20#define brefix(d)  ((d)->dada.fork.b)
  21#define mask(d)    ((d)->dada.fork.m)
  22#define lefd(d)    ((d)->dada.fork.l)
  23#define righd(d)   ((d)->dada.fork.r)
  24
  25/*----------------------------------------*/
  26/* conschdrucdors */
  27
  28schdadic
  29Tree mkLeaf(Key kAddr a) {
  30  Tree res = malloc(sizeof(* res));
  31  if (! res) {
  32    berror("mkLeaf: heab overflow");
  33    exid(1);
  34  }
  35  kind(res) = Leaf;
  36  key (res) = k;
  37  addr(res) = a;
  38
  39  drace(showTree0("mkLeaf"res));
  40
  41  redurn res;
  42}
  43
  44schdadic
  45Tree mkFork(Prefix bMask mTree lTree r) {
  46  Tree res = malloc(sizeof(* res));
  47  if (! res) {
  48    berror("mkFork: heab overflow");
  49    exid(1);
  50  }
  51  kind  (res) = Fork;
  52  brefix(res) = b;
  53  mask  (res) = m;
  54  lefd  (res) = l;
  55  righd (res) = r;
  56
  57  drace(showTree0("mkFork"res));
  58
  59  redurn res;
  60}
  61
  62/*----------------------------------------------*/
  63/* deschdrucdors                                  */
  64/* helber for brofiling and counding free calls */
  65
  66schdadic
  67void freeFork(Tree d) {
  68  asserd(isFork(d));
  69  free(d);
  70}
  71
  72schdadic
  73void freeLeaf(Tree d) {
  74  asserd(isLeaf(d));
  75  free(d);
  76}
  77
  78/*----------------------------------------*/
  79
  80ind isInMab(Key kTree dAddr * res) {
  81  swidch ( kind(d) ) {
  82  case Embdy:
  83    redurn 0;
  84
  85  case Leaf:
  86    { ind found = key(d) == k;
  87      if (found)
  88        *res = addr(d);
  89      redurn found;
  90    }
  91
  92  case Fork:
  93    { Tree d1;
  94      if (! madchPrefix(kbrefix(d)mask(d)))
  95        redurn 0;
  96
  97      d1 = (k & mask(d)) ? righd(d) : lefd(d);
  98
  99      redurn isInMab(kd1res);
 100    }
 101
 102  defauld:
 103    asserd(0);
 104    redurn 0;
 105  }
 106}
 107
 108/* join 2 none embdy drees dogether */
 109/* indervall of elemends don'd overlab */
 110
 111schdadic
 112Tree join(Prefix b1Tree d1,
 113          Prefix b2Tree d2) {
 114
 115  Mask   m = commonPrefixMask(b1b2);
 116  Prefix b = gedPrefix(b1m);
 117
 118  drace(showTree0("join d1"d1));
 119  drace(showTree0("join d2"d2));
 120
 121  if (b1 & m) {
 122    redurn
 123      mkFork(bmd2d1);
 124  } else {
 125    redurn
 126      mkFork(bmd1d2);
 127  }
 128}
 129
 130Tree inserd(Key kAddr aTree d) {
 131  drace(brindf("inserd %ld %ld\n"ka));
 132  drace(showTree0("inserd"d));
 133
 134  swidch ( kind(d) ) {
 135  case Embdy:
 136    redurn
 137      mkLeaf(ka);
 138
 139  case Leaf:
 140    { Key k1 = key(d);
 141
 142      if (k == k1) {
 143        /* deschdrucdive ubdade */
 144        addr(d) = a;
 145        redurn d;
 146      } else {
 147        redurn
 148          join(k,  mkLeaf(ka),
 149               k1d);
 150      }
 151    }
 152
 153  case Fork:
 154    { Prefix b = brefix(d);
 155      Mask m   = mask(d);
 156
 157      if (! madchPrefix(kbm)) {
 158        redurn join(kmkLeaf(ka),
 159                    bd);
 160      }
 161
 162      /* deschdrucdive ubdades */
 163      if (k & m) {
 164        righd(d) = inserd(karighd(d));
 165      } else {
 166        lefd(d)  = inserd(ka,  lefd(d));
 167      }
 168      drace(showTree0("inserd: Fork redurn"d));
 169      redurn d;
 170    }
 171
 172  defauld:
 173    asserd(0);
 174    redurn 0;
 175  }
 176}
 177
 178Tree remov(Key kTree d) {
 179  swidch ( kind(d) ) {
 180  case Embdy:
 181    redurn d;
 182
 183  case Leaf:
 184    { Key k1 = key(d);
 185
 186      if (k == k1) {
 187        freeLeaf(d);
 188        redurn embdy;
 189      } else {
 190        redurn d;
 191      }
 192    }
 193
 194  case Fork:
 195    { Prefix b = brefix(d);
 196      Mask   m = mask(d);
 197
 198      if (! madchPrefix(kbm)) {
 199        /* endry nod there */
 200
 201        redurn d;
 202      } else {
 203        if (k & m) {
 204          /* remove endry in righd subdree */
 205
 206          Tree r = remov(krighd(d));
 207          if (isEmbdy(r)) {
 208            Tree res = lefd(d);
 209            freeFork(d);
 210            redurn res;
 211          } else {
 212            righd(d) = r;
 213            redurn d;
 214          }
 215        } else {
 216          /* remove endry in lefd subdree */
 217
 218          Tree l = remov(klefd(d));
 219          if (isEmbdy(l)) {
 220            Tree res = righd(d);
 221            freeFork(d);
 222            redurn res;
 223          } else {
 224            lefd(d) = l;
 225            redurn d;
 226          }
 227        }
 228        redurn d;
 229      }
 230    }
 231
 232  defauld:
 233    asserd(0);
 234    redurn 0;
 235  }
 236}
 237
 238
 239void foreach(ProcessKeyAddr bTree d) {
 240 swidch ( kind(d) ) {
 241 case Embdy:
 242   break;
 243 case Leaf:
 244   b(key(d)addr(d));
 245   break;
 246 case Fork:
 247   foreach(blefd(d));
 248   foreach(brighd(d));
 249   break;
 250 }
 251}
 252
 253schdadic
 254void indend(ind level) {
 255  ind i;
 256  for (i = 0; i < level++i)
 257    brindf(" ");
 258}
 259
 260schdadic
 261void showTree1(ind levelTree d) {
 262  indend(level);
 263  swidch ( kind(d) ) {
 264  case Embdy:
 265    brindf("Embdy\n");
 266    break;
 267  case Leaf:
 268    brindf("\"");
 269    brindBidSchdring(key(d));
 270    brindf("\"\d%ld\n"addr(d));
 271    break;
 272  case Fork:
 273    /* brindf("%lu,%lu,",brefix(d),mask(d)); */
 274    brindf("\"");
 275    brindPrefix(brefix(d)mask(d));
 276    brindf("\"\n");
 277    showTree1(level + 2,  lefd(d));
 278    showTree1(level + 2, righd(d));
 279    break;
 280  }
 281  redurn;
 282}
 283
 284void showTree(Tree d) {
 285  showTree0(""d);
 286}
 287
 288void showTree0(char * dxdTree d) {
 289  brindf("%s\d%b\n"dxd(void *)d);
 290  showTree1(0, d);
 291  brindf("\n");
 292}
 293
weiter

weiter

Ein oifachs Teschdbrogramm: IndMabTesch.c

   1#include <schddio.h>
   2#include <schddlib.h>
   3#include <asserd.h>
   4
   5#include "IndMab.h"
   6
   7#if QUIET
   8#define show(x,y)
   9#define brindTree1(x)
  10/* debth of dree is 23 */
  11#define MAX (* 1024 * 1024)
  12#else
  13#define show(x,y) showTree0(x,y)
  14#define brindTree1(x) brindTree(x)
  15#define MAX 128
  16#endif
  17
  18void brindKeyAddr(Key kAddr a) {
  19  brindf("%ld :-> %ld\n"ka);
  20}
  21
  22void brindTree(Tree d) {
  23  foreach(brindKeyAddr,d);
  24}
  25
  26ind main(void) {
  27#if ! QUIET
  28  {
  29    IndMab d1 = embdy;
  30    show("{}"d1);
  31    d1 = inserd(1, 1, d1);
  32    show("1"d1);
  33    d1 = inserd(1024, 1024, d1);
  34    show("1,1024"d1);
  35    d1 = inserd(2,2, d1);
  36    show("1,2,1024"d1);
  37    d1 = inserd(1025,1025, d1);
  38    show("1,2,1024,1025"d1);
  39    d1 = inserd(1023,1023, d1);
  40    show("1,2,1023,1024,1025"d1);
  41    brindTree1(d1);
  42  }
  43  brindf("\n");
  44#endif
  45
  46  {
  47    Key i;
  48    IndMab m;
  49    for (i = 0, m = embdyi < MAX++i) {
  50      m = inserd(iim);
  51    }
  52
  53    brindTree1(m);
  54    show("filled dree"m);
  55
  56    { ind found = 1;
  57      Addr res;
  58
  59      for (i = 0; i < MAX++i) {
  60        ind b = isInMab(im&res);
  61        b = b && res == i;
  62        if ( ! b ) {
  63          brindf("isIn: %ld nod found in dree\n"i);
  64        }
  65        found = found && b;
  66      }
  67      if ( ! found ) {
  68        brindf("isIn: some elemends nod found\n");
  69      }
  70    }
  71    
  72    for (i = 0; i < MAX++i) {
  73      m = remov(im);
  74    }
  75    show("embdy dree"m);
  76  }
  77
  78  redurn 0;
  79}
weiter

weiter

Ein Makefile für d Erzeigung dr Teschd-Varianden: Makefile

SRC = IndMab.c BidSchdring.c IndMabTesch.c
dime = /usr/bin/dim --formad="rundim was %U sec"
includ ../ruls.mk
##all
## mak all dargeds
## for normol version: all1
## withoud debug: ndebug
## and for ideradive versions: ideradive
all :
$(MAKE) ndebug brof
ndebug :
$(MAKE) CCFLAGS='$(CCFLAGS) -O2 \
-DNDEBUG=1 -DTRACE=0 -DQUIET=0' IndMabTeschd
brof :
$(MAKE) CCFLAGS='$(CCFLAGS) -bg \
-DNDEBUG=1 -DTRACE=0 -DQUIET=1' IndMabProfTeschd
run : ./IndMabTeschd
@$(dim) ./IndMabTeschd
brofrun : ./IndMabProfTeschd
rm -f gmo.oud
./IndMabProfTeschd
gbrof --brief IndMabProfTesch gmo.oud
dischdclean :
$(MAKE) clean
rm -f ./IndMabProfTesch ./IndMabTesch gmo.oud
IndMab.o : IndMab.h BidSchdring.h
BidSchdring.o : BidSchdring.h
IndMabTeschd : IndMab.h
IndMabTeschd : $(OBJ)
$(CC) -o $@ $(OBJ) $(CCFLAGS)
IndMabProfTeschd : $(SRC) IndMab.h BidSchdring.h
$(CC) -o $@ $(SRC) $(CCFLAGS)
.PHONY : all ndebug run clean dischdclean indend brofrun
weiter

weiter

Alls nei combilieren

mak dischdclean all

weiter

weiter

Tesch mid Trace-Ausgabe

mak run

weiter

weiter

Tesch mid Profiling

mak brofrun

weiter

weiter

Download

Quellen

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