home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ledar34.zip / leda-r-3_4_tar / LEDA-3.4 / src / dict / _ch_hash.c < prev    next >
C/C++ Source or Header  |  1996-09-03  |  7KB  |  347 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA 3.4
  4. +
  5. +  _ch_hash.c
  6. +
  7. +  This file is part of the LEDA research version (LEDA-R) that can be 
  8. +  used free of charge in academic research and teaching. Any commercial
  9. +  use of this software requires a license which is distributed by the
  10. +  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
  11. +  (fax +49 681 31104).
  12. +
  13. +  Copyright (c) 1991-1996  by  Max-Planck-Institut fuer Informatik
  14. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  15. +  All rights reserved.
  16. *******************************************************************************/
  17. #include <LEDA/impl/ch_hash.h>
  18.  
  19. //------------------------------------------------------------------------------
  20. //
  21. //  hashing with chaining and table doubling
  22. //
  23. //  S. Naeher (1994)
  24. //
  25. //  last modfied Dec. 1995:  - missing iteration functions
  26. //                           - bugs in destroy,lookup,rehash
  27. //------------------------------------------------------------------------------
  28.  
  29.  
  30. #define NULLKEY  GenPtr(this)
  31.  
  32.  
  33. int ch_hash::next_pow(int x) const
  34. { // return next power of 2
  35.   int result = 1;    
  36.   while ((x>>=1) > 0) result <<= 1;
  37.   return result;
  38.  }
  39.  
  40. // Iteration
  41.  
  42. ch_hash_item ch_hash::next_item(ch_hash_item q) const
  43. { q = q->succ;
  44.   if (q == &STOP)
  45.   { ch_hash_item stop = table + table_size;
  46.     for(;;)
  47.     { (*(ch_hash_item*)&iterator)++;
  48.       if (iterator == stop) break;
  49.       if (iterator->k != NULLKEY) break;
  50.       if (iterator->succ != &STOP) break;
  51.      }
  52.  
  53.     if (iterator < stop)
  54.       q = (iterator->k != NULLKEY) ? iterator : iterator->succ; 
  55.     else
  56.       q = nil;
  57.    }
  58.   return q;
  59.  }
  60.  
  61. ch_hash_item ch_hash::first_item() const 
  62. { *(ch_hash_item*)&iterator = table;
  63.   ch_hash_item q = table;
  64.   if (q->k == NULLKEY) q = next_item(q); 
  65.   return q;
  66.  }
  67.  
  68.  
  69. ch_hash_item ch_hash::lookup(GenPtr x) const
  70. { ch_hash_item q = table;
  71.  
  72.   ((GenPtr&)STOP.k) = x;
  73.  
  74.   if (int_type())
  75.   { q += (LEDA_ACCESS(int,x) & table_size_1);  // table_size = power of 2
  76.     while (q->k != x) q = q->succ;
  77.    }
  78.   else
  79.   { q += (hash_fct(x) & table_size_1);
  80.     while (q->k == NULLKEY || cmp(q->k,x)) q = q->succ;
  81.    }
  82.  
  83.   return (q == &STOP) ? nil : q;
  84. }
  85.  
  86.  
  87. void ch_hash::change_inf(ch_hash_item p, GenPtr x)
  88. { clear_inf(p->i);
  89.   p->i = x;
  90.   copy_inf(p->i);
  91.  }
  92.  
  93. void ch_hash::del(GenPtr x)
  94.   ch_hash_item p = table + (hash_fct(x) & table_size_1);
  95.  
  96.   if (p->k != NULLKEY && cmp(p->k,x) == 0)
  97.   { clear_key(p->k);
  98.     clear_inf(p->i);
  99.     p->k = NULLKEY;
  100.     count--;
  101.     if (count == low_table) rehash(low_table);
  102.     return;
  103.   }
  104.  
  105.   STOP.k = x;
  106.  
  107.   if (int_type())
  108.      while (LEDA_ACCESS(int,p->succ->k) != LEDA_ACCESS(int,x)) p = p->succ;
  109.   else
  110.      while (p->k == NULLKEY || cmp(p->succ->k,x)) p = p->succ;
  111.  
  112.   ch_hash_item q = p->succ;
  113.  
  114.   if (q==&STOP) return;
  115.  
  116.   clear_key(q->k);
  117.   clear_inf(q->i);
  118.  
  119.   p->succ = q->succ;
  120.   delete q;
  121.   count--;
  122.   if (count == low_table) rehash(low_table);
  123.  }
  124.  
  125.  
  126. void ch_hash::del_item(ch_hash_item q)
  127. { ch_hash_item p = table + (hash_fct(q->k) & table_size_1);
  128.   clear_key(q->k);
  129.   clear_inf(q->i);
  130.   if (p==q) 
  131.      p->k = NULLKEY;
  132.   else
  133.     { while(p->succ != q) p = p->succ;
  134.       p->succ = q->succ;
  135.       delete q;
  136.      }
  137.   count--;
  138.   if (count == low_table) rehash(low_table);
  139.  }
  140.   
  141.   
  142.   
  143.  
  144. ch_hash_item ch_hash::insert(GenPtr x, GenPtr y)
  145.   ch_hash_item p = table + (hash_fct(x) & table_size_1);
  146.   //ch_hash_item p = table + (LEDA_ACCESS(int,x) & table_size_1);
  147.   ch_hash_item q = p;
  148.  
  149.   STOP.k = x;
  150.  
  151.   if (int_type())
  152.      while (p->k != x) p = p->succ;
  153.   else
  154.      while (p->k == NULLKEY || cmp(p->k,x)) p = p->succ;
  155.  
  156.   if (p != &STOP)
  157.   { clear_inf(p->i);
  158.     p->i = y;
  159.     copy_inf(p->i);
  160.     return p;
  161.    }
  162.  
  163.   count++;
  164.   copy_key(x);
  165.   copy_inf(y);
  166.  
  167.   if (q->k == NULLKEY) 
  168.     { q->k = x;
  169.       q->i = y;
  170.      }
  171.   else
  172.     { q->succ = new ch_hash_elem(x,y,q->succ);
  173.       q = q->succ;
  174.      }
  175.  
  176.   if (count == high_table) rehash(high_table);
  177.  
  178.   return q;
  179. }
  180.  
  181.  
  182.  
  183. void ch_hash::destroy()
  184.   for(int i=0; i < table_size; i++) 
  185.   { ch_hash_item p = table+i;
  186.     if (p->k != NULLKEY)
  187.     { clear_key(p->k);
  188.       clear_inf(p->i);
  189.      }
  190.     p = p->succ;
  191.     while (p != &STOP)
  192.     { clear_key(p->k);
  193.       clear_inf(p->i);
  194.       ch_hash_item q = p;
  195.       p = p->succ;
  196.       delete q;
  197.     }
  198.   }
  199.  
  200.   //delete[] table;
  201.   free((char*)table);
  202. }
  203.  
  204.  
  205. void ch_hash::init(int T)
  206.   ch_hash_item p;
  207.   ch_hash_item stop;
  208.  
  209.   table_size = T;
  210.   table_size_1 = T-1;
  211.  
  212.   low_table  = (T > 1024) ? T/2 : -1;
  213.   high_table = 2*T;
  214.  
  215.   //table = new ch_hash_elem[table_size];
  216.   table = (ch_hash_elem*)malloc(table_size*sizeof(ch_hash_elem));
  217.  
  218.   stop = table + table_size;
  219.   for(p=table; p<stop; p++) 
  220.   { p->succ = &STOP;
  221.     p->k = NULLKEY;
  222.   }
  223.  
  224.   count = 0;
  225. }
  226.  
  227. void ch_hash::gen_rehash(int T)
  228.   ch_hash_item old_table = table;
  229.   int old_table_size = table_size;
  230.   int old_count = count;
  231.  
  232.   init(T);
  233.  
  234.   for (int i=0; i<old_table_size; i++)
  235.   { ch_hash_item p = old_table[i].succ;
  236.     while(p != &STOP)
  237.     { ch_hash_item r = p->succ;
  238.       ch_hash_item q = table + (hash_fct(p->k) & table_size_1);
  239.       p->succ = q->succ;
  240.       q->succ = p;
  241.       p = r;
  242.     }
  243.    }
  244.  
  245.   ch_hash_item stop = old_table+old_table_size;
  246.  
  247.   for (ch_hash_item p=old_table; p<stop; p++)
  248.     if (p->k != NULLKEY) 
  249.     { ch_hash_item q = table + (hash_fct(p->k) & table_size_1);
  250.       if (q->k == NULLKEY)
  251.         { q->k = p->k;
  252.           q->i = p->i;
  253.          }
  254.       else
  255.          q->succ = new ch_hash_elem(p->k,p->i,q->succ);
  256.     }
  257.    
  258.   count = old_count;
  259.  
  260.   //delete[] old_table;
  261.   free((char*)old_table);
  262. }
  263.  
  264.  
  265.  
  266. void ch_hash::int_rehash(int T)
  267.   ch_hash_item old_table = table;
  268.  
  269.   int old_table_size = table_size;
  270.   int old_count = count;
  271.  
  272.   init(T);
  273.  
  274.   for (int i=0; i<old_table_size; i++)
  275.   { ch_hash_item p = old_table[i].succ;
  276.     while(p != &STOP)
  277.     { ch_hash_item r = p->succ;
  278.       ch_hash_item q = table + (LEDA_ACCESS(int,p->k) & table_size_1);
  279.       p->succ = q->succ;
  280.       q->succ = p;
  281.       p = r;
  282.      }
  283.    }
  284.  
  285.   ch_hash_item stop = old_table+old_table_size;
  286.   for (ch_hash_item p=old_table; p<stop; p++)
  287.     if (p->k != NULLKEY) 
  288.     { ch_hash_item q = table + (LEDA_ACCESS(int,p->k) & table_size_1);
  289.       if (q->k == NULLKEY)
  290.         { q->k = p->k;
  291.           q->i = p->i;
  292.          }
  293.       else
  294.          q->succ = new ch_hash_elem(p->k,p->i,q->succ);
  295.     }
  296.    
  297.   count = old_count;
  298.  
  299.   //delete[] old_table;
  300.   free((char*)old_table);
  301. }
  302.  
  303.  
  304. void ch_hash::rehash(int T)
  305. { if ( int_type() ) 
  306.      int_rehash(T); 
  307.   else 
  308.      gen_rehash(T); 
  309.  }
  310.  
  311.  
  312. ch_hash::ch_hash(const ch_hash& D)
  313. { ch_hash_item p;
  314.   init(D.table_size);
  315.   for (int i=0; i<table_size; i++)
  316.   { p = D.table[i].succ;
  317.     while(p != &(D.STOP))
  318.     { insert(p->k,p->i);
  319.       D.copy_key(p->k);
  320.       D.copy_inf(p->i);
  321.       p = p->succ;
  322.     }
  323.   }
  324. }
  325.  
  326.  
  327. ch_hash& ch_hash::operator=(const ch_hash& D)
  328. { ch_hash_item p;
  329.   clear();
  330.   for (int i=0; i<D.table_size; i++)
  331.   { p = D.table[i].succ;
  332.     while(p != &(D.STOP))
  333.     { insert(p->k,p->i);
  334.       p = p->succ;
  335.      }
  336.    }
  337.   return *this;
  338. }
  339.  
  340.