home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 1998 October
/
PCWorld_1998-10_cd.bin
/
software
/
prehled
/
komix
/
DATA.Z
/
HashTbl.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-31
|
6KB
|
254 lines
/*---------------------------------------------------------------------------
*
* Copyright (c) 1991 by Westmount Technology B.V., Delft, The Netherlands.
*
* This software is furnished under a license and may be used only in
* accordance with the terms of such license and with the inclusion of
* the above copyright notice. This software or any other copies thereof
* may not be provided or otherwise made available to any other person.
* No title to and ownership of the software is hereby transferred.
*
* The information in this software is subject to change without notice
* and should not be construed as a commitment by Westmount Technology B.V.
*
*---------------------------------------------------------------------------
*
* File : @(#)HashTbl.cxx 1.2 (1.5) (1.2)
* Author : sipi (original by K.E. Gorlen)
* Original date : Wed Apr 15 15:39:04 MET DST 1992
* Description : implementation of hash tables
*
*---------------------------------------------------------------------------
*/
static const char SccsId[]="@(#)HashTbl.cxx 1.2 (1.5) (1.2) 11 Nov 1993 Copyright 1991 Westmount Technology";
#ifndef HASHTBL_HXX
#include <HashTbl.hxx>
#endif
#include <iostream.h>
Hashable::~Hashable() {}
#if ! HAS_TEMPLATES
implement(FlexArray,hashptr);
#endif
unsigned HashTbl::DEFAULT_SIZE = 64;
unsigned HashTbl::EXPANSION_FACTOR = 2;
HashTbl::HashTbl(unsigned size):
contents(setCapacity(size))
{
contents.clear(0);
}
HashTbl::HashTbl(const HashTbl& tbl):
count (tbl.count),
nbits (tbl.nbits),
mask (tbl.mask),
current (tbl.current),
contents (tbl.contents)
{ /* empty */ }
HashTbl::~HashTbl()
{ /* empty */ }
HashTbl&
HashTbl::operator=(const HashTbl& tbl)
{
count = tbl.count;
nbits = tbl.nbits;
mask = tbl.mask;
current = tbl.current;
contents = tbl.contents;
return *this;
}
Hashable*
HashTbl::add(Hashable& object)
{
register int i = findIndexOf(object);
if ( contents.at(i) ) return contents.at(i);
contents.at(i) = &object;
if (++count > capacity()) reSize(capacity()*HashTbl::EXPANSION_FACTOR);
return &object;
}
void
HashTbl::addAll(const HashTbl& tbl)
{
register unsigned n = tbl.contents.capacity();
for (register int i = 0; i < n; i++)
if ( tbl.contents.at(i) ) add( *(tbl.contents.at(i)) );
}
Hashable*
HashTbl::remove(const Hashable& object)
/* Algorithm R, Knuth Vol. 3 p. 527 */
{
register int i = findIndexOf(object);
Hashable* rob = contents.at(i);
if (!rob) /* object does not exist */ return 0;
register int j,r;
while (1) {
contents.at(j=i) = 0;
do {
i = (i-1)&mask;
if (contents.at(i)==0) {
count--;
return rob;
}
r = getIndex(contents.at(i)->hash());
} while ((i<=r&&r<j) || (r<j&&j<i) || (j<i&&i<=r));
contents.at(j) = contents.at(i);
}
}
void
HashTbl::removeAll()
{
contents.clear(0);
count = 0;
}
void
HashTbl::removeAll(const HashTbl& tbl)
{
register unsigned n = tbl.contents.capacity();
for (register int i = 0; i < n; i++)
if ( tbl.contents.at(i) ) remove( *(tbl.contents.at(i)) );
}
void
HashTbl::destructAll()
{
register unsigned n = contents.capacity();
for (register int i = 0; i < n; i++)
if (contents.at(i)) {
hashptr tmp = contents.at(i);
delete tmp;
}
contents.clear(0);
count = 0;
}
int
HashTbl::operator==(const HashTbl& tbl) const
{
if (count!=tbl.count) return 0;
register unsigned n = contents.capacity();
for (register int i=0; i<n; i++) {
if (contents.at(i) &&
tbl.contents.at(findIndexOf( *(contents.at(i)) )) == 0 )
return 0;
}
return 1;
}
Hashable*
HashTbl::first()
{
if(count == 0) return 0;
register unsigned n = contents.capacity();
for (current=0; current<n; current++)
if (contents.at(current)) return contents.at(current);
return 0;
}
Hashable*
HashTbl::next()
{
register unsigned n = contents.capacity();
for (++current;current<n; current++)
if (contents.at(current)) return contents.at(current);
return 0;
}
unsigned
HashTbl::setCapacity(unsigned size)
{
if (size==0) /* error but ignore it */ size++;
current = 0;
count = 0;
nbits = 0;
for (register unsigned s=size; s!=0; s>>=1) nbits++;
if ((size&(size-1)) != 0) nbits++; // round up if not power of 2
size = 1<<nbits;
mask = size-1;
return size; // return hash table size
}
int
HashTbl::getIndex(unsigned long K) const
/* Knuth Vol. 3, Section 6.4, pp. 508-512 */
{
const unsigned long Aw = 0x9E3779B9;
// const unsigned long Aw = 2654435769UL;
// const unsigned long Aw = 40503; use for 16 bit machines?
return ((Aw*K)>>((8*sizeof(unsigned))-nbits)) & mask;
}
int
HashTbl::findIndexOf(const Hashable& object) const
/* Algorithm L, Knuth Vol. 3, p. 519 */
{
register int i;
for (i = getIndex(object.hash()); contents.at(i)!=0; i = (i-1)&mask)
if ((contents.at(i))->isEqual(object)) return i;
return i;
}
void
HashTbl::reSize(unsigned new_size)
{
if (new_size <= count) return;
if (count > 0) {
hashList tmp = contents;
contents.reSize(setCapacity(new_size));
contents.clear(0);
unsigned n = tmp.capacity();
for (int i=0; i < n; i++) {
if (tmp.at(i)) add( *(tmp.at(i)) );
}
}
else contents.reSize(setCapacity(new_size));
}
hash_iter::hash_iter(const HashTbl& t) :
tbl(t),
curr_idx(-1)
{
rewind();
}
hash_iter::~hash_iter()
{
/* empty */
}
void hash_iter::rewind(void)
{
if (tbl.size() == 0) {
curr_idx = -1;
return;
}
register unsigned n = tbl.contents.capacity();
for(curr_idx = 0; curr_idx < n; curr_idx++) {
if (tbl.at(curr_idx))
return;
}
curr_idx = -1;
}
void hash_iter::advance(void)
{
if ( end_of_iteration() )
return;
register unsigned n = tbl.contents.capacity();
for (++curr_idx; curr_idx < n; curr_idx++) {
if (tbl.at(curr_idx))
return;
}
curr_idx = -1;
}