_dp_hash.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:31k
开发平台:

MultiPlatform

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