home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / src / basic / _dp_hash.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-09  |  30.7 KB  |  1,417 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  2.1.1                                                 11-15-1991
  4. +
  5. +
  6. +  _dp_hashing.c
  7. +
  8. +
  9. +  Copyright (c) 1991  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. // Implementierung der Member-Funktionen
  17. // von Dynamic Perfect Hashing nach [DKMMRT]
  18. //
  19. // Fopra / Diplomarbeit
  20. // Michael Wenzel           ( 1989/90 ) 
  21. //
  22. //---------------------------------------------------------------
  23.  
  24.  
  25. #include <LEDA/dp_hashing.h>
  26.  
  27.  
  28. // ----------------------------------------------------------------
  29. // allgemeine Funktionen und Konstanten
  30. // ----------------------------------------------------------------
  31.  
  32.  
  33. // Universum [1..dp_exp_31-1]
  34. // 2-er Potenzen, Shift Operationen sparen
  35. #define dp_exp_31 2147483648
  36. #define dp_exp_30 1073741824
  37. #define dp_exp_29 536870912 
  38. #define dp_exp_28 268435456 
  39. #define dp_exp_27 134217728 
  40. #define dp_exp_26 67108864 
  41. #define dp_exp_25 33554432 
  42.  
  43.  
  44. // Konstante fuer Groesse beim Rehashing 
  45. #define _dp_h_c 1
  46.  
  47. // allgmeine Quadrat- und Multiplikationsfunktion fuer 2-er Potenz
  48. #define sqr(x) ((x)*(x))                  
  49. #define mal_pot2(x,y) ((x)<<(y))
  50.  
  51. // Berechnung von (k*x)%p
  52. // fuer p=2^31+11  ( kleinste Primzahl > 2^31 )
  53.  
  54.  
  55. #define DPMOD_BODY(k,x,dp_erg)\
  56. { unsigned dp_k1=k>>16;\
  57.   unsigned dp_k2=k&65535;\
  58.   unsigned dp_x1=(unsigned(x))>>16;\
  59.   unsigned dp_x2=(unsigned(x))&65535;\
  60.   unsigned dp_e1=dp_k1*dp_x1+((dp_k1*dp_x2+dp_k2*dp_x1)>>16);\
  61.   unsigned dp_e2=dp_k2*dp_x2;\
  62.   unsigned dp_e3=((dp_k1*dp_x2+dp_k2*dp_x1)&65535)<<16;\
  63.   unsigned dp_e5=dp_e2+dp_e3;\
  64.   if ((dp_e2&dp_exp_31)&&(dp_e3&dp_exp_31))\
  65.     dp_e1++;\
  66.   else if (((dp_e2&dp_exp_31)||(dp_e3&dp_exp_31))&&(!(dp_e5&dp_exp_31)))\
  67.      dp_e1++; \
  68.   long dp_f=(dp_e5&0x7fffffff)-22*(dp_e1&0x03ffffff);\
  69.   if (dp_e1&dp_exp_26)\
  70.     if(dp_f<1476394997)\
  71.       dp_f+=671088651;\
  72.     else dp_f-=1476395008;\
  73.   if (dp_e1&dp_exp_27)\
  74.     if(dp_f<805306346)\
  75.       dp_f+=1342177302;\
  76.     else dp_f-=805306357;\
  77.   if (dp_e1&dp_exp_28)\
  78.     if(dp_f<1610612703)\
  79.       dp_f+=536870945;\
  80.     else dp_f-=1610612714;\
  81.   if (dp_e1&dp_exp_29)\
  82.     if(dp_f<1073741758)\
  83.       dp_f+=1073741890;\
  84.     else dp_f-=1073741769;\
  85.   if (dp_e1&dp_exp_30)\
  86.     if(dp_f<2147483527)\
  87.       dp_f+=121;\
  88.     else dp_f-=2147483538;\
  89.   if (dp_e5&dp_exp_31)\
  90.     if (dp_f<0)\
  91.       dp_f+=2147483648;\
  92.     else dp_f-=11;\
  93.   if (dp_f<0)\
  94.     dp_erg=unsigned(dp_f+2147483659);\
  95.   else  dp_erg=unsigned(dp_f);\
  96. }
  97.  
  98. //#ifdef __TURBOC__
  99.  
  100. /* Function "dpmod"  (saves source lines) */
  101.  
  102. static void dpmod(unsigned k, ent x, unsigned& dp_erg) DPMOD_BODY(k,x,dp_erg)
  103.  
  104. //#else
  105.  
  106. /* Macro "dpmod" */
  107.  
  108. //#define dpmod(k,x,dp_erg) DPMOD_BODY(k,x,dp_erg)
  109.  
  110. //#endif
  111.  
  112.  
  113. // ----------------------------------------------------------------
  114. // member-functions of class headertable 
  115. // ----------------------------------------------------------------
  116.  
  117. //-----------------------------------------------------------------
  118. // insert
  119. // fuegt ein Paar (Schluessel,Information) in das Bucket ein
  120. // berechnet Informationen neu
  121. // returns true, falls Element eingefuegt     
  122.  
  123.  
  124. bool headertable::insert(ent a,ent b,stp& erg,int& bed,bool& rehash,
  125.              stp anf,stp ende)
  126.   unsigned dp_erg=0;
  127.   if (!wj)                             // leere Headertable
  128.   { 
  129.     wj=1;
  130.  
  131.     if (!tj)
  132.     { 
  133.       mj=1;
  134.       tj=new subtable(a,b);            // einfach einfuegen
  135.       erg=tj;
  136.     }
  137.     else                               // Tafel war angelegt
  138.     {
  139.       if (mj==1)                       // nur einelementig  
  140.       {
  141.     tj->set_s(a,b);
  142.     erg=tj;
  143.       }
  144.       else                             // groessere Tafel
  145.     if (mj<=4)                     // nur 2 oder 4-elementig  
  146.     {
  147.       tj[0].set_s(a,b);
  148.       erg=tj;
  149.     }
  150.     else
  151.     {
  152.       dpmod(kj,a,dp_erg);
  153.       dp_erg=dp_erg%mal_pot2(sqr(mj),1);
  154.       tj[dp_erg].set_s(a,b);
  155.       erg=tj+dp_erg;
  156.     }
  157.     }
  158.    
  159.     bed+=2; 
  160.     rehash=false;
  161.     return true;         
  162.   }                                    // leere Tafel jetzt mit Element
  163.  
  164.   if (wj==1)                           // Tafel mit einem Element
  165.   { 
  166.     if (mj==1)
  167.     {
  168.       if (a==tj->ke)                   // gleiches Element
  169.       { 
  170.     tj->inf=b;
  171.     erg=tj;
  172.     rehash=false;
  173.     return false; 
  174.       }
  175.       else
  176.       { 
  177.     wj=2;                          // Einfuegen
  178.     bed+=6;
  179.     if (bed>=0)                    // Platz genug?
  180.     { 
  181.       rehash=true;
  182.       return true; 
  183.     }
  184.  
  185.     mj=2;                          // Speicher anfordern
  186.                        // und Elemente verteilen
  187.     stp lj=tj;
  188.     tj=new subtable[2];
  189.     tj[0] = (*lj);
  190.     tj[1].set_s(a,b);
  191.     erg = tj+1;
  192.     
  193.     if ((lj>ende)||(lj<anf)) 
  194.       delete lj;
  195.       }
  196.  
  197.       rehash = false;
  198.       return true;
  199.     }
  200.  
  201.     if (mj<=4)
  202.     {
  203.       if (a==tj[0].ke)               // gleiches Element
  204.       { 
  205.     tj[0].inf=b;
  206.     erg=tj;
  207.     rehash=false;
  208.     return false; 
  209.       }
  210.       else
  211.       { 
  212.     wj = 2;
  213.     bed+=6;
  214.     tj[1].set_s(a,b);
  215.     erg = tj+1;
  216.     rehash=false;
  217.     return true;
  218.       }
  219.     }
  220.     else                               // groessere Tafel
  221.     {
  222.       dpmod(kj,a,dp_erg);
  223.       dp_erg=dp_erg%mal_pot2(sqr(mj),1);
  224.  
  225.       if (a==tj[dp_erg].ke)            // gleiches Element
  226.       { 
  227.     tj[dp_erg].inf = b;
  228.     erg=tj+dp_erg;
  229.     rehash=false;
  230.     return false;
  231.       }
  232.  
  233.       wj=2;
  234.       bed+=6;
  235.  
  236.       if ( tj[dp_erg].ke == EMPTY )    // Position leer
  237.       { 
  238.     tj[dp_erg].set_s(a,b);
  239.     erg=tj+dp_erg;
  240.     rehash=false;
  241.     return true;
  242.       }
  243.       else                             // lokales Rehash
  244.       { 
  245.     stp lj = new subtable(tj[dp_erg]);
  246.     tj[dp_erg].clear();
  247.     int subsize = mal_pot2(sqr(mj),1);
  248.     int injektiv=0;            
  249.                        // injektive Funktion suchen
  250.     
  251.     while (!injektiv)
  252.     { injektiv=1;
  253.       kj=random(1,maxprim-1);
  254.  
  255.       unsigned dp_erg=0;
  256.       dpmod(kj,lj->ke,dp_erg);
  257.       dp_erg=dp_erg%subsize;
  258.       tj[dp_erg]=(*lj);
  259.  
  260.       dpmod(kj,a,dp_erg);
  261.       dp_erg=dp_erg%subsize;
  262.       if ( tj[dp_erg].ke == EMPTY )
  263.       {
  264.         tj[dp_erg].set_s(a,b);
  265.         erg=tj+dp_erg;
  266.       }
  267.       else
  268.       {
  269.         tj[dp_erg].clear(); 
  270.         injektiv=0;
  271.       }
  272.     }                              // Elemente injektiv verteilt 
  273.  
  274.     delete lj;
  275.     rehash=false;
  276.     return true;           
  277.       }
  278.     }
  279.   }                                    // Tafel enthaelt jetzt 2 Elemente
  280.  
  281.   if (wj<4)                            // Tafel mit 2 oder 3 Elementen
  282.   { 
  283.     for (int i1=0; i1<wj ; i1++)
  284.       if (a==tj[i1].ke)                // gleiches Element
  285.       { 
  286.     tj[i1].inf=b;
  287.     erg=tj+i1;
  288.     rehash=false;
  289.     return false; 
  290.       }
  291.  
  292.                        // neues Element
  293.     if (wj==2)
  294.       bed+=10;
  295.     else
  296.       bed+=14;
  297.  
  298.     if (mj==2)
  299.     {
  300.       if (bed>=0)                      // Platz genug?
  301.       { 
  302.     rehash=true;
  303.     return true; 
  304.       }
  305.  
  306.       mj=4;                            // Speicher anfordern
  307.       stp lj=tj;
  308.       tj=new subtable[4];
  309.  
  310.       for (int i1=0; i1<wj ; i1++)
  311.     tj[i1] = lj[i1];
  312.       tj[i1].set_s(a,b);
  313.       erg = tj+wj;
  314.     
  315.       if ((lj>ende)||(lj<anf)) 
  316.     delete[0] lj;
  317.  
  318.       wj++;       
  319.       rehash = false;
  320.       return true;
  321.     }
  322.  
  323.     if (mj==4)
  324.     {
  325.       tj[wj].set_s(a,b);
  326.       erg = tj+wj;
  327.       wj++;       
  328.       rehash=false;
  329.       return true;
  330.     }
  331.     else                               // groessere Tafel
  332.     {
  333.       dpmod(kj,a,dp_erg);
  334.       dp_erg=dp_erg%mal_pot2(sqr(mj),1);
  335.       if ( tj[dp_erg].ke == EMPTY )    // Position leer
  336.       { 
  337.     tj[dp_erg].set_s(a,b);
  338.     erg=tj+dp_erg;
  339.     wj++;       
  340.     rehash=false;
  341.     return true;
  342.       }
  343.       else                             // lokales Rehash
  344.       {
  345.     stp lj = new subtable[++wj];
  346.     int i1=0;
  347.                         // Elemente in Liste kopieren
  348.     for (int i2=0; i1<wj-1 ; i2++ )
  349.     { 
  350.       if ( tj[i2].ke != EMPTY  )
  351.       { 
  352.         lj[i1++]=tj[i2];  
  353.         tj[i2].clear(); 
  354.       }
  355.     }
  356.     lj[i1].set_s(a,b);
  357.  
  358.     int subsize = mal_pot2(sqr(mj),1);
  359.     int injektiv=0;                     // injektive Funktion suchen
  360.     
  361.     while (!injektiv)
  362.     { injektiv=1;
  363.       kj=random(1,maxprim-1);
  364.  
  365.       for (i1=0; (i1<wj) && injektiv ; i1++)
  366.       { 
  367.         dpmod(kj,lj[i1].ke,dp_erg);
  368.         dp_erg=dp_erg%subsize;
  369.  
  370.         if ( tj[dp_erg].ke == EMPTY )
  371.           tj[dp_erg]=lj[i1];
  372.         else
  373.         { 
  374.           injektiv=0;
  375.           for (int g=0;g<i1;g++)     // belegte Positionen loeschen
  376.           { 
  377.         ent help=lj[g].ke;
  378.         dpmod(kj,help,dp_erg);
  379.         dp_erg=dp_erg%subsize;  
  380.         tj[dp_erg].ke = EMPTY ; 
  381.           }
  382.         }
  383.       }                            // Elemente injektiv verteilt  
  384.     }       
  385.  
  386.     delete[0] lj;
  387.     rehash=false;
  388.     return true;           
  389.       }                                // lokales Rehash beendet
  390.     }
  391.   }                                    // Tafel enthaelt jetzt 2 oder 3 Elemente
  392.  
  393.   if (wj==4)                           // Tafel mit 4 Elementen
  394.   { 
  395.     for (int i1=0; i1<4; i1++)
  396.       if (a==tj[i1].ke)                // gleiches Element
  397.       { 
  398.     tj[i1].inf=b;
  399.     erg=tj+i1;
  400.     rehash=false;
  401.     return false; 
  402.       }
  403.   
  404.                        // neues Element einfuegen
  405.     bed+=18;
  406.  
  407.     if (bed>=0)                        // Platz genug?
  408.     { 
  409.       rehash=true;
  410.       return true; 
  411.     }
  412.  
  413.     mj=8;                               // Speicher anfordern
  414.                     // und Elemente verteilen
  415.     stp lj=tj;
  416.     tj=new subtable[128];
  417.     int injektiv=0;       
  418.                     // injektive Funktion suchen
  419.     
  420.     while (!injektiv)
  421.     {
  422.       injektiv=1;
  423.       kj=random(1,maxprim-1);
  424.  
  425.       for (int i1=0; (i1<4) && injektiv ; i1++)
  426.       { 
  427.     dpmod(kj,lj[i1].ke,dp_erg);
  428.     dp_erg=dp_erg%128;
  429.  
  430.     if ( tj[dp_erg].ke == EMPTY )
  431.       tj[dp_erg]=lj[i1];
  432.     else
  433.     { 
  434.       injektiv=0;
  435.       for (int g=0;g<i1;g++)     // belegte Positionen loeschen
  436.       { 
  437.         ent help=lj[g].ke;
  438.         dpmod(kj,help,dp_erg);
  439.         dp_erg=dp_erg%128;  
  440.         tj[dp_erg].ke = EMPTY ; 
  441.       }
  442.     }
  443.       }
  444.       if (injektiv)                  // letztes Element hashen
  445.       {
  446.     dpmod(kj,a,dp_erg);
  447.     dp_erg=dp_erg%128;
  448.     if ( tj[dp_erg].ke == EMPTY )
  449.     { 
  450.       tj[dp_erg].set_s(a,b);
  451.       erg=tj+dp_erg;
  452.     }
  453.     else
  454.     { 
  455.       injektiv=0;
  456.       for (int g=0;g<i1;g++)     // belegte Positionen loeschen
  457.       { 
  458.         ent help=lj[g].ke;
  459.         dpmod(kj,help,dp_erg);
  460.         dp_erg=dp_erg%128;  
  461.         tj[dp_erg].clear() ; 
  462.       }
  463.     }                            // letztes Element 
  464.       }             
  465.     }                                // Elemente injektiv verteilt 
  466.  
  467.     if ((lj>ende)||(lj<anf)) 
  468.       delete[0] lj;
  469.  
  470.     wj=5;                          
  471.     rehash=false;
  472.     return true;           
  473.   }                             // Tafel enthaelt jetzt 5 Elemente
  474.  
  475.                 // Tafel mit >= 5 Elementen
  476.                 // injektives Hashing auf Bucket
  477.  
  478.   int subsize=mal_pot2(sqr(mj),1);
  479.   dpmod(kj,a,dp_erg);
  480.   dp_erg=dp_erg%subsize;
  481.  
  482.   if ( tj[dp_erg].ke == a)         // gleiches Element
  483.   { 
  484.     tj[dp_erg].set_s(a,b);
  485.     erg=tj+dp_erg;
  486.     rehash=false;
  487.     return false;      
  488.   }
  489.  
  490.   int oldscard=wj;
  491.   int subcard=(++wj);
  492.   bed+=mal_pot2(subcard,2)-2;
  493.  
  494.   if ( tj[dp_erg].ke == EMPTY  )    // Position leer -> einfuegen
  495.   { 
  496.     tj[dp_erg].set_s(a,b);
  497.     erg=tj+dp_erg;
  498.     rehash = false;
  499.     return true; 
  500.   }
  501.   else                         // Tafelelement besetzt             
  502.    
  503.     if (subcard<=mj)           // aber noch Platz in Tafel
  504.     {  
  505.       stp lj = new subtable[subcard];
  506.       int i1=0;
  507.                    // Elemente in Liste kopieren
  508.       for (int i2=0; i1<oldscard  ; i2++ )
  509.       {
  510.     if ( tj[i2].ke != EMPTY  )
  511.     {
  512.       lj[i1++]=tj[i2];  
  513.       tj[i2].clear(); 
  514.     }
  515.       }
  516.       lj[i1].set_s(a,b);
  517.                  // lokales Rehash , alle Elemente in Liste lj
  518.  
  519.       int injektiv=0;
  520.       while (!injektiv)          // injektive Funktion suchen
  521.       { 
  522.     injektiv=1;
  523.     kj=random(1,maxprim-1);
  524.  
  525.     for (i1=0; (i1<subcard) && injektiv ; i1++)
  526.     { 
  527.       dpmod(kj,lj[i1].ke,dp_erg);
  528.       dp_erg=dp_erg%subsize;
  529.       if ( tj[dp_erg].ke == EMPTY )
  530.       {
  531.         tj[dp_erg]=lj[i1]; 
  532.         erg=tj+dp_erg;
  533.       }
  534.       else
  535.       {
  536.         injektiv=0;                // Injektivitaet verletzt
  537.         for (int g=0;g<i1;g++)     // belegte Positionen loeschen
  538.         {
  539.           ent help=lj[g].ke;
  540.           dpmod(kj,help,dp_erg);
  541.           dp_erg=dp_erg%subsize;  
  542.           tj[dp_erg].ke = EMPTY ; 
  543.         }
  544.       }
  545.     }                       // Elemente getestet
  546.  
  547.       }                         // naechster Versuch oder fertig
  548.  
  549.       delete[0] lj;
  550.     }                             // subcard<=mj
  551.  
  552.     else                          // |Wj|>Mj , d.h. Groesse der
  553.                   // Subtable verdoppeln
  554.     { 
  555.       if (bed>=0)                 // Kontrolle des Platzverbrauchs
  556.       {
  557.     rehash = true;
  558.     return true;    
  559.       }
  560.       else                        // Platz in Ordnung             
  561.                   // Untertafel verdoppeln
  562.       { 
  563.     int oldssize= mal_pot2(sqr(mj),1);
  564.     int i1=0;
  565.                   // Elemente in Liste retten
  566.     stp lj = new subtable[subcard]; 
  567.     for (int i2=0; i1<oldscard ; i2++)
  568.       if ( tj[i2].ke != EMPTY  )
  569.         lj[i1++]=tj[i2];
  570.     lj[i1].set_s(a,b);
  571.  
  572.     for ( ; mj<wj ; mj<<=1 ) ;    // Subtable vergroessern
  573.     subsize = mal_pot2(sqr(mj),1); 
  574.  
  575.     if ((tj>ende)||(tj<anf))      // Speicherverwaltung
  576.       delete[0] tj;
  577.  
  578.     tj=new subtable[subsize]; 
  579.     int injektiv=0;
  580.                       // injektive Funktion suchen
  581.     while (!injektiv)       
  582.     {
  583.       injektiv=1;
  584.       kj=random(1,maxprim-1);
  585.       for (i1=0; (i1<subcard) && injektiv ; i1++)
  586.       {
  587.         dpmod(kj,lj[i1].ke,dp_erg);
  588.         dp_erg=dp_erg%subsize;
  589.         if ( tj[dp_erg].ke == EMPTY )
  590.         { 
  591.           tj[dp_erg]=lj[i1]; 
  592.           erg=tj+dp_erg;
  593.         }
  594.  
  595.          else                       // Injektivitaet verletzt
  596.          {
  597.            injektiv=0;
  598.            for (int g=0;g<i1;g++)   // Subtables saeubern
  599.            {
  600.          ent help=lj[g].ke;
  601.          dpmod(kj,help,dp_erg);
  602.          dp_erg=dp_erg%subsize;
  603.          tj[dp_erg].ke = EMPTY ; 
  604.            }
  605.  
  606.          }
  607.       }                             // alle Elemente getestet
  608.  
  609.     }                               // naechster Versuch oder fertig
  610.  
  611.     delete[0] lj;
  612.     rehash = false;
  613.     return true;
  614.       }
  615.     }
  616.   }                       // insert
  617.    
  618. //-----------------------------------------------------------------
  619. // dinsert
  620. // fuegt ein Paar (Schluessel,Information) in das Bucket ein
  621. // benutzt Informationen aus Konstruktor oder Rehash_all
  622. // gibt true zurueck, falls erfolgreich
  623.  
  624.  
  625. int headertable::dinsert(ent a,ent b,
  626.               stp ende,stp& wo,stp& erg)
  627.  
  628. {
  629.   if (mj==1)                    // nur ein Element in Tafel 
  630.   {                             // und Tafel anlegen  
  631.     tj=wo;
  632.     wo++; 
  633.     tj->set_s(a,b);    
  634.     erg=tj;
  635.     return true;  
  636.   }                             // leere Tafel jetzt mit Element
  637.  
  638.   if (mj==2)                    // zwei Elemente in Tafel 
  639.   {
  640.     if (!tj)                    // und Tafel anlegen
  641.     { 
  642.       wj=1;
  643.       tj=wo;
  644.       wo+=2; 
  645.       tj[0].set_s(a,b);    
  646.       erg=tj;
  647.       return true;  
  648.     }                           // leere Tafel jetzt mit Element
  649.     else
  650.     { 
  651.       if (a==tj[0].ke)
  652.       {
  653.     tj[0].inf = b;
  654.     erg = tj;
  655.     return false;
  656.       }
  657.       wj=2;
  658.       tj[1].set_s(a,b);
  659.       erg=tj+1;
  660.       return true;
  661.     }
  662.   }
  663.  
  664.   if (mj<=4)                    // max 4 Elemente in Tafel 
  665.   {
  666.     if (!tj)                    // und Tafel anlegen
  667.     { 
  668.       wj=1;
  669.       tj=wo;
  670.       wo+=4; 
  671.       tj[0].set_s(a,b);    
  672.       erg=tj;
  673.       return true;  
  674.     }                           // leere Tafel jetzt mit Element
  675.     else
  676.     { 
  677.       for (int i1=0; i1<wj; i1++)
  678.     if (a==tj[i1].ke)
  679.     {
  680.       tj[i1].inf = b;
  681.       erg = tj+i1;
  682.       return false;
  683.     }
  684.  
  685.       tj[wj].set_s(a,b);
  686.       erg=tj+wj;
  687.       wj++;
  688.       return true;
  689.     }
  690.   }
  691.  
  692.  
  693.  
  694.   if (!tj)                      // Tafel muss angelegt werden
  695.                 // Tafel mit meheren Elementen
  696.                 // erstes Element kommt hinein
  697.   { 
  698.     int q=mal_pot2(sqr(mj),1);  // Platz anfordern aus Pool
  699.     tj=wo;
  700.     wo+=q; 
  701.     if (wo>ende+1)
  702.       error_handler(1,"memory allocation error");
  703.  
  704.     kj=random(1,maxprim-1);     // erstes Element einfuegen
  705.     unsigned dp_erg=0;
  706.     dpmod(kj,a,dp_erg);
  707.     dp_erg=dp_erg%q;
  708.     tj[dp_erg].set_s(a,b);
  709.     erg=tj+dp_erg;
  710.     wj = 1;                     // jetzt aktuelles wj
  711.     return true;       
  712.   }                             // leere Tafel jetzt mit 1.Element
  713.  
  714.                 // Tafel ist schon angelegt und enthaelt Element
  715.                 // Tafel bekommt mindestens 5 Elemente
  716.   unsigned dp_erg=0;
  717.   int subsize=mal_pot2(sqr(mj),1);
  718.   dpmod(kj,a,dp_erg);
  719.   dp_erg=dp_erg%subsize;
  720.  
  721.   if ( tj[dp_erg].ke == a)           // gleicher Schluessel
  722.   { 
  723.     tj[dp_erg].set_s(a,b);
  724.     erg=tj+dp_erg;
  725.     return false;      
  726.   }
  727.  
  728.   if ( tj[dp_erg].ke == EMPTY  )     // Position leer
  729.   { tj[dp_erg].set_s(a,b);   
  730.     erg=tj+dp_erg;
  731.   }
  732.  
  733.   else                          // Position besetzt -> lokales Rehash 
  734.   {  
  735.                 // Elemente sammeln
  736.      stp lj = new subtable[wj+1];
  737.      int i1=0;
  738.      int i2=0;
  739.      for (i2=0; i1<wj ; i2++)   // Elemente in Liste kopieren
  740.      { if ( tj[i2].ke != EMPTY  )
  741.        { lj[i1++]=tj[i2];  
  742.      tj[i2].clear() ; 
  743.        }
  744.      }
  745.  
  746.      lj[i1++].set_s(a,b);         // i1 = wj+1
  747.  
  748.                   // lokales Rehash , alle Elemente in Liste lj
  749.      int injektiv=0;
  750.                   // injektive Funktion suchen
  751.      while (!injektiv)         
  752.      {
  753.        injektiv=1;
  754.        kj=random(1,maxprim-1);
  755.  
  756.        for (i2=0; (i2<i1) && injektiv ; i2++)
  757.        { 
  758.      dpmod(kj,lj[i2].ke,dp_erg);
  759.      dp_erg=dp_erg%subsize;
  760.      if ( tj[dp_erg].ke == EMPTY )
  761.      {
  762.        tj[dp_erg]=lj[i2]; 
  763.        erg=tj+dp_erg;
  764.      }
  765.      else                      // Injektivitaet verletzt
  766.      {
  767.        injektiv=0;
  768.        for (int g=0;g<i2;g++)  // Subtables saeubern
  769.        {
  770.          ent help=lj[g].ke;
  771.          unsigned dp_erg=0;
  772.          dpmod(kj,help,dp_erg);
  773.          dp_erg=dp_erg%subsize;
  774.          tj[dp_erg].ke = EMPTY ;
  775.        }
  776.      }
  777.        }                           // alle Elemente getestet 
  778.  
  779.      }                             // neuer Versuch oder fertig
  780.  
  781.      delete[0] lj;
  782.   }
  783.  
  784.   wj++;                           // aktuelle Anzahl updaten
  785.   return true;
  786.  
  787. }
  788.  
  789.  
  790. // ----------------------------------------------------------------
  791. // lookup
  792. // sucht nach Eintrag mit Schluessel a
  793. // gibt Pointer auf Eintrag zurueck, falls gefunden
  794. // 0 sonst
  795.  
  796. stp headertable::lookup(ent a)
  797.  
  798.    if (!wj)  return 0;              // Headertable leer
  799.  
  800.    if (mj==1)                       // Headertable einelementig
  801.    { 
  802.      if (a==tj->ke) 
  803.        return tj;
  804.      else
  805.        return 0;
  806.    }
  807.  
  808.    if (mj<=4)                       // Tafel mit max 4 Elementen
  809.    { 
  810.      for (int i1=0; i1<wj; i1++)
  811.        if (a==tj[i1].ke) 
  812.      return tj+i1;
  813.      return 0;
  814.    }
  815.                     // Headertable mit mehr als 4 Subtables
  816.    unsigned dp_erg=0;
  817.    dpmod(kj,a,dp_erg);
  818.    dp_erg=dp_erg%(mal_pot2(sqr(mj),1));   // Position
  819.  
  820.    if (tj[dp_erg].ke==a)
  821.      return tj+dp_erg;
  822.    else
  823.      return 0; 
  824.  } 
  825.  
  826. // ----------------------------------------------------------------
  827. // del
  828. // loescht Element in Tafel
  829. // gibt true zurueck, wenn erfolgreich
  830.  
  831. bool headertable::del(ent a,stp anf,stp ende)
  832.  
  833. {
  834.   if (!wj) return false;             // leere Headertable
  835.  
  836.   if (mj==1)                         // Headertable einelementig
  837.   { 
  838.     if (a==tj->ke) 
  839.     {
  840.       wj=0;                          // Schluessel gefunden
  841.       tj->clear() ;
  842.       if ((tj<anf)||(tj>ende))
  843.       {
  844.     delete tj;
  845.     tj = 0;
  846.     mj = 0;
  847.       } 
  848.       return true;    
  849.     }
  850.     else
  851.       return false;
  852.   }
  853.      
  854.   if (mj<=4)           
  855.   { 
  856.     if (wj>1)                        // Headertable mit mind 2 Elementen
  857.     {
  858.       for (int i1=0; i1<wj; i1++)
  859.       { 
  860.     if (tj[i1].ke==a)            // Element gefunden
  861.     { 
  862.       wj--;
  863.       tj[i1]=tj[wj];             // Loch fuellen
  864.       tj[wj].clear();
  865.       return true;
  866.     }
  867.       }
  868.       return false;
  869.     }
  870.     else                               // ein Element in Bucket
  871.     {
  872.       if (tj[0].ke==a) 
  873.       {
  874.     wj=0;                          // Schluessel gefunden
  875.     tj[0].clear() ;
  876.     if ((tj<anf)||(tj>ende))
  877.     {
  878.       delete[0] tj;
  879.       tj = 0;
  880.       mj = 0;
  881.     } 
  882.     return true;    
  883.       }
  884.       else
  885.     return false;
  886.     }
  887.   }
  888.      
  889.                       // Headertable mit mehreren Subtables
  890.   unsigned dp_erg=0;
  891.   dpmod(kj,a,dp_erg);
  892.   dp_erg=dp_erg%(mal_pot2(sqr(mj),1));   // Position
  893.  
  894.   if (tj[dp_erg].ke==a)
  895.   {
  896.     wj--;                             // Schluessel gefunden
  897.     tj[dp_erg].clear() ;
  898.  
  899.     if (wj==0)                        // Bucket nun leer
  900.       if ((tj<anf)||(tj>ende))
  901.       {
  902.     delete[0] tj;
  903.     tj = 0;
  904.     mj = 0;
  905.       } 
  906.     return true;    
  907.   } 
  908.   else return false;
  909. }
  910.  
  911. // ---------------------------------------------------------
  912. // give_elements()
  913. // haengt Elemente der Tafel an Liste an
  914. // gibt Anzahl der Elemente zurueck
  915.  
  916.  
  917. int headertable::give_elements(stp& wo,stp anf,stp ende)
  918.  
  919.   int j=0;
  920.  
  921.   if (!wj) { 
  922.          if ( tj && ((tj<anf)||(tj>ende))) 
  923.          {
  924.            if (mj>1)
  925.          delete[0] tj;
  926.            else 
  927.          delete tj;
  928.  
  929.            tj = 0;
  930.            mj = 0;
  931.          }
  932.          return 0;
  933.        }
  934.  
  935.   if (mj==1)                    // Headertable einelementig
  936.   { 
  937.     (*wo)=(*tj);                // Element kopieren
  938.     wo++;
  939.     if ((tj<anf)||(tj>ende))     // gebe Speicher frei
  940.     {
  941.       delete tj;
  942.       tj = 0;
  943.       mj = 0;
  944.     }
  945.     return 1; 
  946.   }
  947.  
  948.   if (mj<=4)                     // Headertable maximal vierelementig
  949.   { 
  950.     j=0;   
  951.     while ( (tj[j].ke != EMPTY) && (j<mj) )
  952.     { 
  953.       (*wo)=tj[j];
  954.       wo++;
  955.       j++;
  956.     }
  957.  
  958.     if ((tj<anf)||(tj>ende))     // gebe Speicher frei
  959.     { 
  960.       delete[0] tj;
  961.       tj = 0;
  962.       mj = 0;
  963.     }
  964.     return j; 
  965.   }
  966.  
  967.                  // Headertable mit meheren Elementen
  968.   bool weiter=true;
  969.   int subsize=mal_pot2(sqr(mj),1);
  970.   j=0;
  971.  
  972.   for (int k=0;(k<subsize)&&weiter;k++)  // suche Elemente
  973.     if ( tj[k].ke != EMPTY  )
  974.     {                                    // haenge Element an Liste
  975.       (*wo)=tj[k];
  976.       wo++; j++;
  977.       if (j>=wj) weiter=false; 
  978.     }
  979.   if ((tj<anf)||(tj>ende))               // gebe Speicher frei
  980.   { 
  981.     delete[0] tj;
  982.     tj = 0;
  983.     mj = 0;
  984.   }
  985.   return j;
  986. }
  987.  
  988. // ----------------------------------------------------------------
  989. // member-functions of class dphash
  990. // ----------------------------------------------------------------
  991.  
  992. // -------------------------------------------------------
  993. // rehash_all
  994. //
  995. // stellt Headertables neu auf, um Platzverbrauch korrekt
  996. // zu halten
  997. // fuegt Element dann neu ein
  998.  
  999. stp dphash::rehash_all( ent x=EMPTY , ent y=0 )
  1000.  
  1001.   int i,i1,j,nsave,platz;
  1002.   unsigned dp_erg=0;
  1003.  
  1004.   stp erg=0;
  1005.   stp l=new subtable[n];         // Sammle Elemente in Liste l
  1006.  
  1007.   i=0;
  1008.   stp pos = l;
  1009.   nsave = ( x == EMPTY ? n : n-1 );
  1010.  
  1011.   while ( (i<sM) && (nsave>0) )  // Sammle Element aus allen Headertables
  1012.   { 
  1013.     if (htablep[i])
  1014.     {
  1015.       nsave -= htablep[i]->give_elements(pos,anf,ende) ;
  1016.       delete htablep[i];
  1017.     }
  1018.     i++;   
  1019.   }
  1020.  
  1021.   if ( x != EMPTY )               // fuege neues Element hinzu
  1022.     l[n-1].set_s(x,y);
  1023.  
  1024.   free ((char*)htablep);          // Speicher freigeben
  1025.   if (anf) 
  1026.     delete[0] anf; 
  1027.                         // neue Parameter setzen
  1028.  
  1029.   M=int((1+_dp_h_c)*n);
  1030.   sM = int(((4.0/3.0)*wursechs)*(1+_dp_h_c)*n);
  1031.  
  1032.                       // Speicher allokieren
  1033.   htablep=(htp*) calloc(sM,sizeof(htp));  // schneller als new+init
  1034.   int* buckets=new int[n];
  1035.  
  1036.   if (!htablep)
  1037.     error_handler(1,"memory overflow");
  1038.  
  1039.   platz=n;
  1040.   i1=0;
  1041.   while (!i1)                    // Top-Funktion suchen
  1042.   { 
  1043.     bed=0;
  1044.     k=random(1,maxprim-1);
  1045.     for (i=0;i<n;i++)           // Hashe alle Elemente
  1046.     {
  1047.       ent help=l[i].ke;
  1048.       dpmod(k,help,dp_erg);
  1049.       dp_erg=dp_erg%sM;
  1050.       buckets[i] = dp_erg;      // Merke Headertable
  1051.  
  1052.       if (!htablep[dp_erg]) 
  1053.     htablep[dp_erg] = new headertable;
  1054.  
  1055.                 // Aendere Headertables
  1056.       int f=++(htablep[dp_erg]->wj);
  1057.       int* groesse=&(htablep[dp_erg]->mj);
  1058.  
  1059.       if (f<=2)
  1060.      (*groesse)++;
  1061.       else
  1062.     if (*groesse<f)
  1063.     { 
  1064.       (*groesse)<<=1;      
  1065.   
  1066.       if (*groesse==4)       // vergroessere Feld
  1067.         platz++;
  1068.       else
  1069.         if (*groesse==8)     // Uebergang von Feld auf Tafel
  1070.           platz+=123;
  1071.         else
  1072.           platz+=3*sqr(*groesse)/2; 
  1073.     }
  1074.     else                     // Tafel nicht vergroessert
  1075.       platz--;
  1076.  
  1077.       bed+=mal_pot2(f,2)-2; 
  1078.     }                            // alle Elemente gehasht
  1079.  
  1080.                  // bed-=(((8.0*sqr(M))/sM)+2*M);
  1081.     float _bed=(wursechs+2)*M;   // Vereinfachung durch Einsetzen von sM
  1082.     bed-=int(_bed);
  1083.     i1=(bed<0);                  // kontrolliere Platz
  1084.  
  1085.     if (!i1)                     // nicht erfolgreich, saeubere Headertables
  1086.     {
  1087.       platz=n;
  1088.       for (j=0; j<sM; j++)
  1089.     if (htablep[j]) 
  1090.     { 
  1091.       delete htablep[j];
  1092.       htablep[j] = 0 ;   
  1093.     }
  1094.     }
  1095.  
  1096.   }                              // Top-Funktion gefunden
  1097.  
  1098.  
  1099.   anf=new subtable[platz];        // allokiere Speicher fuer alle Subtables
  1100.   wo=anf;
  1101.   ende=anf+platz-1;
  1102.  
  1103.   for (i=0; i<n; i++)             // fuege Elemente wieder ein
  1104.   { 
  1105.     int bucket=buckets[i];  
  1106.     htablep[bucket]->dinsert(l[i].ke,l[i].inf,ende,wo,erg);
  1107.   }
  1108.  
  1109.   delete buckets;
  1110.   delete[0] l;
  1111.   return erg;
  1112. }
  1113.  
  1114. // --------------------------------------------------------
  1115. // insert
  1116. //
  1117. // fuegt Element in die entsprechende Headertable ein
  1118.  
  1119. stp dphash::insert(ent x,ent y)
  1120.  
  1121.   if ( (unsigned)x>maxuni )  
  1122.     error_handler(2,string("key %d out of range",x));
  1123.  
  1124.   copy_key(x);
  1125.   copy_inf(y);
  1126.  
  1127.   unsigned dp_erg=0;
  1128.   dpmod(k,x,dp_erg);
  1129.   dp_erg=dp_erg%sM;                   // Toptafel
  1130.  
  1131.   bool rehash = false;
  1132.   stp  erg    = 0;
  1133.  
  1134.   if ( !htablep[dp_erg] ) 
  1135.     htablep[dp_erg] = new headertable;
  1136.  
  1137.   if ( htablep[dp_erg]->insert(x,y,erg,bed,rehash,anf,ende) )  n++;
  1138.  
  1139.   if ( rehash )  erg=rehash_all(x,y);
  1140.  
  1141.   return erg;
  1142. }
  1143.  
  1144. // --------------------------------------------------------
  1145. // del
  1146. //
  1147. // loescht Element aus entsprechender Headertable
  1148.  
  1149. void dphash::del(ent x)
  1150.  
  1151.  
  1152.   if ( (unsigned)x>maxuni )  
  1153.     error_handler(2,string("key %d out of range",x));
  1154.  
  1155. // s.n. :
  1156.  
  1157. stp p = lookup(x);
  1158. if (p==0) return;
  1159. clear_key(p->ke);
  1160. clear_inf(p->inf);
  1161.  
  1162.  
  1163.   unsigned dp_erg=0;
  1164.   dpmod(k,x,dp_erg);
  1165.   dp_erg=dp_erg%sM;                   // Toptafel
  1166.  
  1167.   if ( !htablep[dp_erg] ) return;     // Headertable nicht vorhanden
  1168.                       // in Toptafel loeschen
  1169.  
  1170.   if ( htablep[dp_erg]->del(x,anf,ende) ) n--;     
  1171.  
  1172.   if ( !htablep[dp_erg]->wj )
  1173.   { 
  1174.     delete htablep[dp_erg];
  1175.     htablep[dp_erg] = 0;
  1176.   }
  1177.  
  1178.   if ((n*(1+3*_dp_h_c)<M) && (n>3))
  1179.     rehash_all(); 
  1180.  
  1181.  
  1182. // -------------------------------------------------------
  1183. // member,lookup,change_inf
  1184. //
  1185. // suchen in Headertable nach Element mit Schluessel
  1186. // change_inf setzt Information des Elementes auf y
  1187.  
  1188. int dphash::member(ent x)
  1189.  
  1190.   if ( (unsigned)x>maxuni )  
  1191.     error_handler(2,string("key %d out of range",x));
  1192.  
  1193.   unsigned dp_erg=0;
  1194.   dpmod(k,x,dp_erg);
  1195.   dp_erg=dp_erg%sM;                   // Toptafel
  1196.  
  1197.   if (!htablep[dp_erg])
  1198.     return 0;                         // Headertable nicht vorhanden
  1199.  
  1200.   return ( htablep[dp_erg]->lookup(x) ? 1 : 0 ); 
  1201.  
  1202. }
  1203.  
  1204. stp dphash::lookup(ent x)                 // wie member
  1205.  
  1206.   if ( (unsigned)x>maxuni )  
  1207.     error_handler(2,string("key %d out of range",x));
  1208.  
  1209.   unsigned dp_erg=0;
  1210.   dpmod(k,x,dp_erg);
  1211.   dp_erg=dp_erg%sM;                   // Toptafel
  1212.  
  1213.   if (!htablep[dp_erg]) 
  1214.     return 0;
  1215.  
  1216.   stp y=htablep[dp_erg]->lookup(x);
  1217.   return y ;
  1218.  
  1219. }
  1220.  
  1221. stp dphash::change_inf(ent x,ent y)       // wie member
  1222.  
  1223.   if ( (unsigned)x>maxuni )  
  1224.     error_handler(2,string("key %d out of range",x));
  1225.  
  1226.   unsigned dp_erg=0;
  1227.   dpmod(k,x,dp_erg);
  1228.   dp_erg=dp_erg%sM;                   // Toptafel
  1229.  
  1230.  
  1231.   if (!htablep[dp_erg])
  1232.     return 0;
  1233.  
  1234.   stp t = htablep[dp_erg]->lookup(x) ;
  1235.   if (t)
  1236.     t->inf = y ;
  1237.   return t;
  1238.  
  1239. }
  1240.  
  1241. // -------------------------------------------------------
  1242. // clear
  1243. //
  1244. // loescht alle Elemente und
  1245. // setzt Hashing auf Leerzustand
  1246.  
  1247. void dphash::clear()
  1248.  
  1249.   stp l = new subtable[n];
  1250.   stp pos=l;
  1251.  
  1252.   for (int i=0;i<sM;i++)           // Headertables loeschen
  1253.     if (htablep[i])
  1254.     { 
  1255.       htablep[i]->give_elements(pos,anf,ende);
  1256.       delete htablep[i];                         
  1257.     }
  1258.  
  1259.   free ((char*)htablep) ;          // Speicher freigeben
  1260.  
  1261.   if (anf) 
  1262.     delete[0] anf;
  1263.  
  1264.   delete[0] l;
  1265.  
  1266.   n = 0;                           // Leerinitialisierung
  1267.   M=4;
  1268.   sM=13;
  1269.   k=random(1,maxprim-1);
  1270.   bed=-17;
  1271.   htablep=(htp*) calloc(sM,sizeof(htp));
  1272.   anf = wo = ende = 0;
  1273.  
  1274. }
  1275.  
  1276. // ------------------------------------------------------------
  1277. // Konstruktoren und Destruktor
  1278.  
  1279. dphash::dphash()
  1280.  
  1281.   n=0;
  1282.   M=4;
  1283.   sM=13;
  1284.   k=random(1,maxprim-1);
  1285.   bed=-17;
  1286.   htablep=(htp*) calloc(sM,sizeof(htp));
  1287.   anf = wo = ende = 0;
  1288.  
  1289. }
  1290.  
  1291. dphash::dphash(int an,ent* keys,ent* inhalte)   
  1292.                       // wie rehash_all
  1293.                       // die Elemente stehen aber schon in Listen
  1294.   int i,i1,j,nsave,platz;
  1295.   unsigned dp_erg=0;
  1296.   stp erg=0;
  1297.  
  1298.   n=an;
  1299.   M=int((1+_dp_h_c)*n);
  1300.   sM = int(((4.0/3.0)*wursechs)*(1+_dp_h_c)*n);
  1301.  
  1302.   htablep=(htp*) calloc(sM,sizeof(htp));
  1303.   int* buckets = new int[n];
  1304.  
  1305.   if (!htablep)
  1306.     error_handler(1,"memory overflow");
  1307.  
  1308.   platz=n;
  1309.   i1=0;
  1310.  
  1311.   while (!i1)
  1312.   {
  1313.     bed=0;
  1314.     k=random(1,maxprim-1);
  1315.  
  1316.     for (i=0;i<n;i++)
  1317.     {
  1318.       ent help=keys[i];
  1319.       if ( (unsigned)help>maxuni )  
  1320.      error_handler(2,string("key %d out of range",help));
  1321.  
  1322.       dpmod(k,help,dp_erg);
  1323.       dp_erg=dp_erg%sM;
  1324.       buckets[i] = dp_erg;
  1325.  
  1326.       if (!htablep[dp_erg]) 
  1327.     htablep[dp_erg] = new headertable;
  1328.  
  1329.       int f=++(htablep[dp_erg]->wj);
  1330.       int* groesse=&(htablep[dp_erg]->mj);
  1331.  
  1332.       if (f<=2)
  1333.      (*groesse)++;
  1334.       else
  1335.     if (*groesse<f)
  1336.     { 
  1337.       (*groesse)<<=1;      
  1338.   
  1339.       if (*groesse==4)       // vergroessere Feld
  1340.         platz++;
  1341.       else
  1342.         if (*groesse==8)     // Uebergang von Feld auf Tafel
  1343.           platz+=123;
  1344.         else
  1345.           platz+=3*sqr(*groesse)/2; 
  1346.     }
  1347.     else                     // Tafel nicht vergroessert
  1348.       platz--;
  1349.  
  1350.       bed+=mal_pot2(f,2)-2; 
  1351.     }
  1352.     
  1353.                  // bed-=(((8.0*sqr(M))/sM)+2*M);
  1354.     float _bed=(wursechs+2)*M;   // Vereinfachung durch Einsetzen von sM
  1355.     bed-=int(_bed);
  1356.     i1=(bed<0);
  1357.  
  1358.     if (!i1)
  1359.     { 
  1360.       platz=n;
  1361.       for (j=0; j<sM; j++)
  1362.     if (htablep[j]) 
  1363.     { 
  1364.       delete htablep[j];
  1365.       htablep[j] = 0;   
  1366.     }
  1367.     }
  1368.   }
  1369.  
  1370.   nsave=an;
  1371.   anf=new subtable[platz];
  1372.  
  1373.   wo=anf;
  1374.   ende=wo+platz-1;
  1375.   n=0;
  1376.  
  1377.   for (i=0; i<nsave; i++)
  1378.   {
  1379.     int bucket = buckets[i];
  1380.     n += (htablep[bucket]->dinsert(keys[i],inhalte[i],ende,wo,erg));
  1381.   } 
  1382.  
  1383.   delete buckets;
  1384.  
  1385.   if ((n*(1+3*_dp_h_c)<M) && (n>3))
  1386.     rehash_all();   
  1387.  
  1388. }
  1389.  
  1390. dphash::~dphash()
  1391.   clear();                            // loesche alles
  1392.  
  1393.   free ((char*)htablep);              // gebe Speicher frei
  1394.   if (anf) delete[0] anf;
  1395.  
  1396.   n=M=sM=0;
  1397.   k=0;
  1398.   anf=wo=ende=0;
  1399.   htablep=0;
  1400.  
  1401. }
  1402.