home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / src / basic / _ch_hash.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  10.1 KB  |  360 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  2.1.1                                                 11-15-1991
  4. +
  5. +
  6. +  _ch_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. #include <LEDA/ch_hashing.h>
  17.  
  18. //----------------------------------------------------------------------
  19. // hashing mit verkettung  
  20. // Walter Zimmer
  21. // Literatur : Kurt Mehlhorn : "Datenstrukturen und eff. Algorithmen "
  22. // modifiziert von Stefan Naeher (Mai 1989)
  23. //----------------------------------------------------------------------
  24.  
  25.  
  26. //----------------------------------------------------------------------
  27. // gibt zeiger auf wbook_el mit key x zurueck ; falls x nicht im 
  28. // wbook => return 0
  29. //----------------------------------------------------------------------
  30.  
  31. ch_hashing_el* ch_hashing::lookup(ent x) const
  32.   TRACE(( " lookup : key = %d \n",int(x) ));
  33.  
  34.   hash_list* L = *(get_list(x)) ;             
  35.   list_item p = ( L ? get_list_el(x,L) : 0); 
  36.                              //  L == 0  oder  x nicht in L  =>  p = 0
  37.  
  38.   if ( p )  return (*L)[p];
  39.   else return 0;                    //falls x nicht in ch_hashing => return 0
  40. }
  41.  
  42.  
  43. hash_list_ptr* ch_hashing::get_list(ent x) const 
  44. { return &( hash_table[(*f)(x) & divisor]);}
  45.  
  46. //----------------------------------------------------------------------
  47. // get_List_el(x,L) : gibt zeiger auf Listenelement mit key x
  48. //                     zurueck , falls x in Liste L , sonst return 0
  49. //----------------------------------------------------------------------
  50.  
  51. list_item ch_hashing::get_list_el(ent x, hash_list* L) const
  52. {
  53.   TRACE(( " get_list_el(x) : x = %d",int(x) ));
  54.  
  55.   list_item p ;
  56.  
  57.   // nicht forall_listitems benutzen , da dieses makro die
  58.   // iteratoren der liste veraendert , die wbook aber selber 
  59.   // fuer die eigenen makros benoetigt
  60.  
  61.  for (  p = L->first();  p ; p = L->succ(p) ) 
  62.    if ( cmp((*L)[p]->k,x) == 0 ) return p;
  63.  
  64.  return 0;  // falls element x nicht in l => return 0
  65. }
  66.  
  67. //----------------------------------------------------------------------
  68. // del(x) : streicht element mit key x aus ch_hashing und gibt zeiger
  69. //          auf das gestrichene element zurueck ;
  70. //          falls kein element mit key x im baum => error 
  71. //----------------------------------------------------------------------
  72.  
  73. ch_hashing_el* ch_hashing::del(ent x)
  74. {
  75.   TRACE(( " del : key = %d \n",int(x) ));
  76.  
  77.   --counter;
  78.  
  79.   hash_list* L = *( get_list(x) ); 
  80.   list_item p = ( L ? get_list_el(x,L) : 0 ); 
  81.                 // falls L == 0  oder x nicht in L  =>   p = 0
  82.  
  83.   if ( p )   return (L->del(p) );
  84.   return 0;
  85. }
  86.  
  87. //----------------------------------------------------------------------
  88. // insert(x,y) : fuegt neues element mit key x und entry y in ch_hashing ein
  89. // und gibt zeiger auf das eingefuegte element zurueck
  90. // bem : mehrere elemente mit gleichem key moeglich
  91. //----------------------------------------------------------------------
  92.  
  93. ch_hashing_el* ch_hashing::insert(ent x, ent y)
  94. {
  95.    TRACE(( " insert : key = %d \n",int(x) ));
  96.  
  97.    ++ counter ;
  98.  
  99.    hash_list_ptr* L =  get_list(x);
  100.    hash_list_ptr l = *L;
  101.  
  102.    copy_key(x);
  103.    copy_inf(y);
  104.  
  105.    if ( l )         // falls l != 0 => liste existiert schon 
  106.        l->push( new ch_hashing_el(x,y) ); 
  107.    else             //  falls l == 0 => liste muss erst angelegt werden
  108.    {
  109.      // neue liste anlegen und den zeiger an der stelle (*L) in die  
  110.      // hash_table eintragen  
  111.  
  112.    (*L) = new hash_list(new ch_hashing_el(x,y));
  113.    }
  114.  
  115.    return  (*L)->head() ;     // nicht l->head() !!!
  116. }
  117. //----------------------------------------------------------------------
  118. // print(): ausgabe des wbooks ( nur zu testzwecken ) fuer int
  119. //----------------------------------------------------------------------
  120.  
  121. void ch_hashing::print() const
  122. {
  123.   TRACE(( " print  \n"));
  124.  
  125.   cout << " size = " << size() << "\n";
  126.   cout << " table_size = " << table_size << "\n";
  127.  
  128.   hash_list_ptr* p;
  129.   for (  p = &hash_table[table_size-1]; p >= &hash_table[0]                              ; p-- )
  130.      if ( *p )     // falls an dieser stelle liste existiert
  131.      {
  132.        ch_hashing_el* x ;
  133.        forall(x,(*(*p)) )
  134.        {   
  135.          print_key(x->k);
  136.          cout << " ";
  137.        }
  138.        cout << "\n"; 
  139.      }
  140. }
  141.  
  142.  
  143. void ch_hashing::init_iterator()
  144. { if (iterator!=0) (*iterator)->init_iterator();
  145.   iterator = 0;
  146. }
  147.  
  148. //----------------------------------------------------------------------
  149. // move_iterator() : setzt iterator auf das naechste element und
  150. // gibt zeiger auf dieses zurueck ( fuer macros )
  151. //----------------------------------------------------------------------
  152.  
  153. ch_hashing_el* ch_hashing::move_iterator()
  154. {
  155.   TRACE(( " move_iterator \n" ));
  156.  
  157.   ch_hashing_el* p;
  158.  
  159.   if (!iterator)                // iterator am anfang oder wbook leer
  160.   {
  161.     if ( empty() ) return 0;    // falls wbook leer => return 0
  162.     else                        // sonst existiert nichtleere liste 
  163.     {
  164.       // suche nach der ersten nichtleeren liste ; 
  165.       // beginne bei hash_table[tablesize-1]
  166.  
  167.       for ( iterator = &hash_table[ table_size-1 ];                                         ( (*iterator) == 0  || (*iterator)->empty() ); --iterator )
  168.     ;
  169.     }
  170.   }
  171.   else 
  172.     if ( !( (*iterator)->next_element(p) ) )
  173.        // falls next_element(p) 0 zurueckgibt => am ende einer liste
  174.        //  =>  naechste nichtleere liste suchen
  175.     {
  176.       do
  177.       {
  178.      if ( iterator == &hash_table[0] )
  179.            {  iterator = 0 ; return 0; }
  180.      else   -- iterator;
  181.       }
  182.       while (  !(*iterator) ||  (*iterator)->empty()   );
  183.  
  184.       // falls noch nichtleere liste existiert
  185.  
  186.  
  187.     }
  188.     else return p;  // noch nicht am ende der aktuellen liste
  189.  
  190.  // am anfang einer nichtleeren liste => init_iter + next_el(p)
  191.  
  192.  (*iterator)->init_iterator();
  193.  (*iterator)->next_element(p);
  194.   return p;
  195. }
  196. //----------------------------------------------------------------------
  197. //   remove() : gibt speicherplatz der hash_table wieder frei , d.h.   
  198. //   benutzer muss neue table_size und hashfct angeben , falls er ch_hashing
  199. //   nochmal benutzen will
  200. //----------------------------------------------------------------------
  201.  
  202. void ch_hashing::remove()
  203. {
  204.   TRACE(( " remove \n"));
  205.  
  206.   clear();
  207.   delete[table_size] hash_table; //  ??? listen loeschen ???
  208.   hash_table = 0;
  209.   table_size = divisor = 0;
  210.   f = 0;
  211. }
  212.  
  213. //----------------------------------------------------------------------
  214. //   clear() : speicherplatz der hash_table bleibt erhalten , doch
  215. //   werden alle elemente geloescht ;
  216. //   table_size , divisor , cmp , und hash_fct bleiben erhalten
  217. //----------------------------------------------------------------------
  218.  
  219. void ch_hashing::clear()
  220. {
  221.   TRACE(( " clear \n"));
  222.  
  223.   for (int i = table_size-1 ; i >= 0 ; --i)
  224.      if ( hash_table[i] )    // falls liste existiert => inhalt loeschen
  225.      {  while (! hash_table[i]->empty()) 
  226.         { ch_hashing_el* p = hash_table[i]->pop(); 
  227.           clear_key(p->k);
  228.           clear_inf(p->e);
  229.           delete p;
  230.          }
  231.         delete ( hash_table[i] );
  232.         hash_table[i] = 0; 
  233.      }
  234.   counter = 0; 
  235.   iterator = 0;
  236. }
  237.  
  238. //----------------------------------------------------------------------
  239. // (1) : neuen speicherplatz  anlegen und mit 0 initialisieren
  240. // (2) : inhalt des wbooks in neu angelegten  speicherplatz uebertragen
  241. //       mit neuer tablesize und neuer hash_fct ; 
  242. // (3) : altes wbook durch remove loeschen
  243. // (4) : neues besetzen der members
  244. //----------------------------------------------------------------------
  245.  
  246. void ch_hashing::new_size_or_fct(int Table_size,hash_fct F)
  247. {
  248.    TRACE(( " new_size_or_fct \n"));
  249.  
  250.  
  251.    Table_size = round(Table_size);
  252.    int Divisor = Table_size -1;
  253.    int Counter = counter;
  254.  
  255. // (1)
  256.  
  257.    hash_list_ptr* Hash_table = new hash_list_ptr[Table_size];
  258.    for ( int i=Table_size-1 ; i >= 0 ; --i ) Hash_table[i] = 0; 
  259.  
  260. // (2)
  261.  
  262.    ch_hashing_el* p;
  263.    forall_in_ch_hashing( p , (*this) )  
  264.    {
  265.      hash_list_ptr* L = & ( Hash_table [ F(p->k) & Divisor ] );
  266.  
  267.      if ( *L ) 
  268.        (*L)->push( new ch_hashing_el(p) );
  269.      else   //  falls *L == 0  =>  liste muss erst angelegt werden
  270.       (*L) = new hash_list( new ch_hashing_el(p));
  271.    } 
  272.    
  273.  
  274. // (3)
  275.    
  276.    remove();
  277.  
  278. // (4)
  279.  
  280.    f = F;
  281.    counter = Counter;
  282.    hash_table = Hash_table;
  283.    table_size = Table_size;
  284.    divisor = Divisor;
  285.    // iterator durch remove() auf 0 gesetzt
  286. }
  287. //----------------------------------------------------------------------
  288.  
  289. ch_hashing::ch_hashing(int Table_size,hash_fct F)
  290.      // auf Vax genuegt int fuer table_size
  291. {
  292.       TRACE(( " ch_hashing-konstruktor \n"));
  293.  
  294.   table_size = round(Table_size);
  295.   divisor = table_size-1;
  296.   f = F;
  297.   hash_table = new hash_list_ptr[table_size];
  298.   for ( register int i = table_size-1; i >= 0 ; --i )
  299.       hash_table[i] = 0;
  300.   counter = 0;
  301.   iterator = 0;
  302. }
  303.  
  304. ch_hashing::ch_hashing()
  305. {
  306.   table_size = round(default_hash_tablesize);
  307.   divisor = table_size-1;
  308.   f = default_hash_fct;
  309.   hash_table = new hash_list_ptr[table_size];
  310.   for ( register int i = table_size-1; i >= 0 ; --i )
  311.       hash_table[i] = 0;
  312.   counter = 0;
  313.   iterator = 0;
  314. }
  315.  
  316. ch_hashing::ch_hashing(int Table_size)
  317. {
  318.   table_size = round(Table_size);
  319.   divisor = table_size-1;
  320.   f = default_hash_fct;
  321.   hash_table = new hash_list_ptr[table_size];
  322.   for ( register int i = table_size-1; i >= 0 ; --i )
  323.       hash_table[i] = 0;
  324.   counter = 0;
  325.   iterator = 0;
  326. }
  327.  
  328. ch_hashing::ch_hashing(hash_fct F)
  329. {
  330.   table_size = round(default_hash_tablesize);
  331.   divisor = table_size-1;
  332.   f = F;
  333.   hash_table = new hash_list_ptr[table_size];
  334.   for ( register int i = table_size-1; i >= 0 ; --i )
  335.       hash_table[i] = 0;
  336.   counter = 0;
  337.   iterator = 0;
  338. }
  339.  
  340. //----------------------------------------------------------------------
  341. // runded auf die naechste zweierpotenz auf
  342. //----------------------------------------------------------------------
  343.  
  344. int ch_hashing::round(int a) const
  345. {
  346.   TRACE(( "round\n"));
  347.  
  348.   for (int  b = 1 ; a > 0 ; a >>= 1)   b <<= 1;
  349.   return b-1;
  350. }
  351.  
  352.  
  353. int default_hash_fct(ent& x) { return int(x); }
  354.  
  355. //----------------------------------------------------------------------
  356. // end of hash.c
  357. //----------------------------------------------------------------------
  358.