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 >
Wrap
C/C++ Source or Header
|
1996-09-03
|
7KB
|
347 lines
/*******************************************************************************
+
+ LEDA 3.4
+
+ _ch_hash.c
+
+ This file is part of the LEDA research version (LEDA-R) that can be
+ used free of charge in academic research and teaching. Any commercial
+ use of this software requires a license which is distributed by the
+ LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
+ (fax +49 681 31104).
+
+ Copyright (c) 1991-1996 by Max-Planck-Institut fuer Informatik
+ Im Stadtwald, 66123 Saarbruecken, Germany
+ All rights reserved.
+
*******************************************************************************/
#include <LEDA/impl/ch_hash.h>
//------------------------------------------------------------------------------
//
// hashing with chaining and table doubling
//
// S. Naeher (1994)
//
// last modfied Dec. 1995: - missing iteration functions
// - bugs in destroy,lookup,rehash
//------------------------------------------------------------------------------
#define NULLKEY GenPtr(this)
int ch_hash::next_pow(int x) const
{ // return next power of 2
int result = 1;
while ((x>>=1) > 0) result <<= 1;
return result;
}
// Iteration
ch_hash_item ch_hash::next_item(ch_hash_item q) const
{ q = q->succ;
if (q == &STOP)
{ ch_hash_item stop = table + table_size;
for(;;)
{ (*(ch_hash_item*)&iterator)++;
if (iterator == stop) break;
if (iterator->k != NULLKEY) break;
if (iterator->succ != &STOP) break;
}
if (iterator < stop)
q = (iterator->k != NULLKEY) ? iterator : iterator->succ;
else
q = nil;
}
return q;
}
ch_hash_item ch_hash::first_item() const
{ *(ch_hash_item*)&iterator = table;
ch_hash_item q = table;
if (q->k == NULLKEY) q = next_item(q);
return q;
}
ch_hash_item ch_hash::lookup(GenPtr x) const
{ ch_hash_item q = table;
((GenPtr&)STOP.k) = x;
if (int_type())
{ q += (LEDA_ACCESS(int,x) & table_size_1); // table_size = power of 2
while (q->k != x) q = q->succ;
}
else
{ q += (hash_fct(x) & table_size_1);
while (q->k == NULLKEY || cmp(q->k,x)) q = q->succ;
}
return (q == &STOP) ? nil : q;
}
void ch_hash::change_inf(ch_hash_item p, GenPtr x)
{ clear_inf(p->i);
p->i = x;
copy_inf(p->i);
}
void ch_hash::del(GenPtr x)
{
ch_hash_item p = table + (hash_fct(x) & table_size_1);
if (p->k != NULLKEY && cmp(p->k,x) == 0)
{ clear_key(p->k);
clear_inf(p->i);
p->k = NULLKEY;
count--;
if (count == low_table) rehash(low_table);
return;
}
STOP.k = x;
if (int_type())
while (LEDA_ACCESS(int,p->succ->k) != LEDA_ACCESS(int,x)) p = p->succ;
else
while (p->k == NULLKEY || cmp(p->succ->k,x)) p = p->succ;
ch_hash_item q = p->succ;
if (q==&STOP) return;
clear_key(q->k);
clear_inf(q->i);
p->succ = q->succ;
delete q;
count--;
if (count == low_table) rehash(low_table);
}
void ch_hash::del_item(ch_hash_item q)
{ ch_hash_item p = table + (hash_fct(q->k) & table_size_1);
clear_key(q->k);
clear_inf(q->i);
if (p==q)
p->k = NULLKEY;
else
{ while(p->succ != q) p = p->succ;
p->succ = q->succ;
delete q;
}
count--;
if (count == low_table) rehash(low_table);
}
ch_hash_item ch_hash::insert(GenPtr x, GenPtr y)
{
ch_hash_item p = table + (hash_fct(x) & table_size_1);
//ch_hash_item p = table + (LEDA_ACCESS(int,x) & table_size_1);
ch_hash_item q = p;
STOP.k = x;
if (int_type())
while (p->k != x) p = p->succ;
else
while (p->k == NULLKEY || cmp(p->k,x)) p = p->succ;
if (p != &STOP)
{ clear_inf(p->i);
p->i = y;
copy_inf(p->i);
return p;
}
count++;
copy_key(x);
copy_inf(y);
if (q->k == NULLKEY)
{ q->k = x;
q->i = y;
}
else
{ q->succ = new ch_hash_elem(x,y,q->succ);
q = q->succ;
}
if (count == high_table) rehash(high_table);
return q;
}
void ch_hash::destroy()
{
for(int i=0; i < table_size; i++)
{ ch_hash_item p = table+i;
if (p->k != NULLKEY)
{ clear_key(p->k);
clear_inf(p->i);
}
p = p->succ;
while (p != &STOP)
{ clear_key(p->k);
clear_inf(p->i);
ch_hash_item q = p;
p = p->succ;
delete q;
}
}
//delete[] table;
free((char*)table);
}
void ch_hash::init(int T)
{
ch_hash_item p;
ch_hash_item stop;
table_size = T;
table_size_1 = T-1;
low_table = (T > 1024) ? T/2 : -1;
high_table = 2*T;
//table = new ch_hash_elem[table_size];
table = (ch_hash_elem*)malloc(table_size*sizeof(ch_hash_elem));
stop = table + table_size;
for(p=table; p<stop; p++)
{ p->succ = &STOP;
p->k = NULLKEY;
}
count = 0;
}
void ch_hash::gen_rehash(int T)
{
ch_hash_item old_table = table;
int old_table_size = table_size;
int old_count = count;
init(T);
for (int i=0; i<old_table_size; i++)
{ ch_hash_item p = old_table[i].succ;
while(p != &STOP)
{ ch_hash_item r = p->succ;
ch_hash_item q = table + (hash_fct(p->k) & table_size_1);
p->succ = q->succ;
q->succ = p;
p = r;
}
}
ch_hash_item stop = old_table+old_table_size;
for (ch_hash_item p=old_table; p<stop; p++)
if (p->k != NULLKEY)
{ ch_hash_item q = table + (hash_fct(p->k) & table_size_1);
if (q->k == NULLKEY)
{ q->k = p->k;
q->i = p->i;
}
else
q->succ = new ch_hash_elem(p->k,p->i,q->succ);
}
count = old_count;
//delete[] old_table;
free((char*)old_table);
}
void ch_hash::int_rehash(int T)
{
ch_hash_item old_table = table;
int old_table_size = table_size;
int old_count = count;
init(T);
for (int i=0; i<old_table_size; i++)
{ ch_hash_item p = old_table[i].succ;
while(p != &STOP)
{ ch_hash_item r = p->succ;
ch_hash_item q = table + (LEDA_ACCESS(int,p->k) & table_size_1);
p->succ = q->succ;
q->succ = p;
p = r;
}
}
ch_hash_item stop = old_table+old_table_size;
for (ch_hash_item p=old_table; p<stop; p++)
if (p->k != NULLKEY)
{ ch_hash_item q = table + (LEDA_ACCESS(int,p->k) & table_size_1);
if (q->k == NULLKEY)
{ q->k = p->k;
q->i = p->i;
}
else
q->succ = new ch_hash_elem(p->k,p->i,q->succ);
}
count = old_count;
//delete[] old_table;
free((char*)old_table);
}
void ch_hash::rehash(int T)
{ if ( int_type() )
int_rehash(T);
else
gen_rehash(T);
}
ch_hash::ch_hash(const ch_hash& D)
{ ch_hash_item p;
init(D.table_size);
for (int i=0; i<table_size; i++)
{ p = D.table[i].succ;
while(p != &(D.STOP))
{ insert(p->k,p->i);
D.copy_key(p->k);
D.copy_inf(p->i);
p = p->succ;
}
}
}
ch_hash& ch_hash::operator=(const ch_hash& D)
{ ch_hash_item p;
clear();
for (int i=0; i<D.table_size; i++)
{ p = D.table[i].succ;
while(p != &(D.STOP))
{ insert(p->k,p->i);
p = p->succ;
}
}
return *this;
}