mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-25 13:30:34 +05:00
1654 lines
30 KiB
C++
1654 lines
30 KiB
C++
#ifndef FILE_HASHTABL
|
|
#define FILE_HASHTABL
|
|
|
|
/**************************************************************************/
|
|
/* File: hashtabl.hh */
|
|
/* Author: Joachim Schoeberl */
|
|
/* Date: 01. Jun. 95 */
|
|
/**************************************************************************/
|
|
|
|
namespace netgen
|
|
{
|
|
|
|
/**
|
|
Abstract data type HASHTABLE.
|
|
Hash is done by one INDEX
|
|
*/
|
|
class BASE_INDEX_HASHTABLE
|
|
{
|
|
protected:
|
|
/// keys are stored in this table
|
|
TABLE<INDEX,1> hash;
|
|
|
|
public:
|
|
///
|
|
BASE_INDEX_HASHTABLE (int size)
|
|
: hash (size) { };
|
|
|
|
protected:
|
|
///
|
|
int HashValue (const INDEX & ind) const
|
|
{
|
|
return ind % hash.Size() + 1;
|
|
}
|
|
|
|
///
|
|
int Position (int bnr, const INDEX & ind) const;
|
|
};
|
|
|
|
///
|
|
template <class T>
|
|
class INDEX_HASHTABLE : private BASE_INDEX_HASHTABLE
|
|
{
|
|
///
|
|
TABLE<T,1> cont;
|
|
|
|
public:
|
|
///
|
|
inline INDEX_HASHTABLE (int size);
|
|
///
|
|
inline void Set (const INDEX & hash, const T & acont);
|
|
///
|
|
inline const T & Get (const INDEX & ahash) const;
|
|
///
|
|
inline bool Used (const INDEX & ahash) const;
|
|
///
|
|
inline int GetNBags () const;
|
|
///
|
|
inline int GetBagSize (int bnr) const;
|
|
///
|
|
inline void GetData (int bnr, int colnr, INDEX & ahash, T & acont) const;
|
|
|
|
///
|
|
inline void PrintMemInfo (ostream & ost) const;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
class BASE_INDEX_2_HASHTABLE
|
|
{
|
|
protected:
|
|
///
|
|
TABLE<INDEX_2> hash;
|
|
|
|
public:
|
|
///
|
|
BASE_INDEX_2_HASHTABLE () { ; }
|
|
|
|
BASE_INDEX_2_HASHTABLE (int size)
|
|
: hash (size) { };
|
|
|
|
///
|
|
void PrintStat (ostream & ost) const;
|
|
void BaseSetSize(int s) {hash.SetSize(s);}
|
|
//protected:
|
|
///
|
|
int HashValue (const INDEX_2 & ind) const
|
|
{
|
|
return (ind.I1() + ind.I2()) % hash.Size() + 1;
|
|
}
|
|
///
|
|
int Position (int bnr, const INDEX_2 & ind) const
|
|
{
|
|
for (int i = 1; i <= hash.EntrySize (bnr); i++)
|
|
if (hash.Get(bnr, i) == ind)
|
|
return i;
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
|
|
///
|
|
template <class T>
|
|
class INDEX_2_HASHTABLE : public BASE_INDEX_2_HASHTABLE
|
|
{
|
|
///
|
|
TABLE<T> cont;
|
|
|
|
public:
|
|
///
|
|
INDEX_2_HASHTABLE () { ; }
|
|
|
|
INDEX_2_HASHTABLE (int size)
|
|
: BASE_INDEX_2_HASHTABLE (size), cont(size)
|
|
{ ; }
|
|
|
|
///
|
|
void SetSize(int s)
|
|
{
|
|
cont.SetSize(s);
|
|
BaseSetSize(s);
|
|
}
|
|
|
|
///
|
|
void Set (const INDEX_2 & ahash, const T & acont)
|
|
{
|
|
int bnr = HashValue (ahash);
|
|
int pos = Position (bnr, ahash);
|
|
if (pos)
|
|
cont.Set (bnr, pos, acont);
|
|
else
|
|
{
|
|
hash.Add1 (bnr, ahash);
|
|
cont.Add1 (bnr, acont);
|
|
}
|
|
}
|
|
|
|
///
|
|
const T & Get (const INDEX_2 & ahash) const
|
|
{
|
|
int bnr = HashValue (ahash);
|
|
int pos = Position (bnr, ahash);
|
|
return cont.Get (bnr, pos);
|
|
}
|
|
|
|
T & Get (const INDEX_2 & ahash)
|
|
{
|
|
int bnr = HashValue (ahash);
|
|
int pos = Position (bnr, ahash);
|
|
return cont.Get (bnr, pos);
|
|
}
|
|
|
|
///
|
|
bool Used (const INDEX_2 & ahash) const
|
|
{
|
|
return Position (HashValue (ahash), ahash) > 0;
|
|
}
|
|
///
|
|
int GetNBags () const
|
|
{
|
|
return cont.Size();
|
|
}
|
|
|
|
///
|
|
int GetBagSize (int bnr) const
|
|
{
|
|
return cont.EntrySize (bnr);
|
|
}
|
|
|
|
///
|
|
void GetData (int bnr, int colnr,
|
|
INDEX_2 & ahash, T & acont) const
|
|
{
|
|
ahash = hash.Get(bnr, colnr);
|
|
acont = cont.Get(bnr, colnr);
|
|
}
|
|
|
|
///
|
|
void SetData (int bnr, int colnr,
|
|
const INDEX_2 & ahash, const T & acont)
|
|
{
|
|
hash.Set(bnr, colnr, ahash);
|
|
cont.Set(bnr, colnr, acont);
|
|
}
|
|
|
|
///
|
|
void PrintMemInfo (ostream & ost) const
|
|
{
|
|
ost << "Hash: " << endl;
|
|
hash.PrintMemInfo (ost);
|
|
ost << "Cont: " << endl;
|
|
cont.PrintMemInfo (ost);
|
|
}
|
|
|
|
|
|
void DeleteData ()
|
|
{
|
|
int n = hash.Size();
|
|
hash.SetSize (n);
|
|
cont.SetSize (n);
|
|
}
|
|
|
|
|
|
class Iterator
|
|
{
|
|
const INDEX_2_HASHTABLE & ht;
|
|
int bagnr, pos;
|
|
public:
|
|
Iterator (const INDEX_2_HASHTABLE & aht,
|
|
int abagnr, int apos)
|
|
: ht(aht), bagnr(abagnr), pos(apos)
|
|
{ ; }
|
|
|
|
int BagNr() const { return bagnr; }
|
|
int Pos() const { return pos; }
|
|
|
|
Iterator operator++ (int)
|
|
{
|
|
Iterator it(ht, bagnr, pos);
|
|
++(*this);
|
|
return it;
|
|
}
|
|
Iterator& operator++()
|
|
{
|
|
pos++;
|
|
while (bagnr < ht.GetNBags() &&
|
|
pos == ht.GetBagSize(bagnr+1))
|
|
{
|
|
pos = 0;
|
|
bagnr++;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
std::pair<INDEX_2, T> operator*()
|
|
{
|
|
return std::make_pair(ht.hash[bagnr][pos], ht.cont[bagnr][pos]);
|
|
}
|
|
|
|
bool operator != (int i) const
|
|
{
|
|
return bagnr != i;
|
|
}
|
|
|
|
};
|
|
|
|
Iterator Begin () const
|
|
{
|
|
Iterator it(*this, 0, -1);
|
|
it++;
|
|
return it;
|
|
}
|
|
|
|
int End() const
|
|
{
|
|
return GetNBags();
|
|
}
|
|
|
|
Iterator begin () const
|
|
{
|
|
Iterator it(*this, 0, -1);
|
|
it++;
|
|
return it;
|
|
}
|
|
|
|
int end() const
|
|
{
|
|
return GetNBags();
|
|
}
|
|
|
|
void GetData (const Iterator & it,
|
|
INDEX_2 & ahash, T & acont) const
|
|
{
|
|
ahash = hash[it.BagNr()][it.Pos()];
|
|
acont = cont[it.BagNr()][it.Pos()];
|
|
}
|
|
|
|
const INDEX_2 & GetHash (const Iterator & it) const
|
|
{ return hash[it.BagNr()][it.Pos()]; }
|
|
|
|
const T & GetData (const Iterator & it) const
|
|
{ return cont[it.BagNr()][it.Pos()]; }
|
|
|
|
void DoArchive (Archive & ar)
|
|
{
|
|
ar & hash & cont;
|
|
}
|
|
|
|
};
|
|
|
|
template <typename T>
|
|
inline ostream & operator<< (ostream & ost, const INDEX_2_HASHTABLE<T> & ht)
|
|
{
|
|
for (typename INDEX_2_HASHTABLE<T>::Iterator it = ht.Begin();
|
|
it != ht.End(); it++)
|
|
{
|
|
ost << ht.GetHash(it) << ": " << ht.GetData(it) << endl;
|
|
}
|
|
|
|
return ost;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
class BASE_INDEX_3_HASHTABLE
|
|
{
|
|
protected:
|
|
///
|
|
TABLE<INDEX_3> hash;
|
|
|
|
public:
|
|
///
|
|
BASE_INDEX_3_HASHTABLE () { ; }
|
|
BASE_INDEX_3_HASHTABLE (int size)
|
|
: hash (size) { };
|
|
|
|
protected:
|
|
///
|
|
int HashValue (const INDEX_3 & ind) const
|
|
{
|
|
return (ind.I1() + ind.I2() + ind.I3()) % hash.Size() + 1;
|
|
}
|
|
|
|
///
|
|
int Position (int bnr, const INDEX_3 & ind) const
|
|
{
|
|
const INDEX_3 * pi = &hash.Get(bnr, 1);
|
|
int n = hash.EntrySize(bnr);
|
|
for (int i = 1; i <= n; ++i, ++pi)
|
|
{
|
|
if (*pi == ind)
|
|
return i;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
///
|
|
template <class T>
|
|
class INDEX_3_HASHTABLE : private BASE_INDEX_3_HASHTABLE
|
|
{
|
|
///
|
|
TABLE<T> cont;
|
|
|
|
public:
|
|
///
|
|
inline INDEX_3_HASHTABLE () { ; }
|
|
inline INDEX_3_HASHTABLE (int size);
|
|
///
|
|
inline void Set (const INDEX_3 & ahash, const T & acont);
|
|
///
|
|
inline const T & Get (const INDEX_3 & ahash) const;
|
|
///
|
|
inline bool Used (const INDEX_3 & ahash) const;
|
|
///
|
|
inline int GetNBags () const;
|
|
///
|
|
inline int GetBagSize (int bnr) const;
|
|
///
|
|
inline void SetData (int bnr, int colnr, const INDEX_3 & ahash, const T & acont);
|
|
///
|
|
inline void GetData (int bnr, int colnr, INDEX_3 & ahash, T & acont) const;
|
|
/// returns position, if not existing, will create (create == return 1)
|
|
inline int PositionCreate (const INDEX_3 & ahash, int & bnr, int & colnr);
|
|
///
|
|
inline void SetSize (int size);
|
|
|
|
///
|
|
inline void PrepareSet (const INDEX_3 & ahash);
|
|
///
|
|
inline void AllocateElements ();
|
|
|
|
///
|
|
inline void PrintMemInfo (ostream & ost) const;
|
|
///
|
|
inline void DeleteData ();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Iterator
|
|
{
|
|
const INDEX_3_HASHTABLE & ht;
|
|
int bagnr, pos;
|
|
public:
|
|
Iterator (const INDEX_3_HASHTABLE & aht,
|
|
int abagnr, int apos)
|
|
: ht(aht), bagnr(abagnr), pos(apos)
|
|
{ ; }
|
|
|
|
int BagNr() const { return bagnr; }
|
|
int Pos() const { return pos; }
|
|
|
|
void operator++ (int)
|
|
{
|
|
// cout << "begin Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl;
|
|
pos++;
|
|
while (bagnr < ht.GetNBags() &&
|
|
pos == ht.GetBagSize(bagnr+1))
|
|
{
|
|
pos = 0;
|
|
bagnr++;
|
|
}
|
|
// cout << "end Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl;
|
|
}
|
|
|
|
bool operator != (int i) const
|
|
{
|
|
return bagnr != i;
|
|
}
|
|
|
|
};
|
|
|
|
Iterator Begin () const
|
|
{
|
|
Iterator it(*this, 0, -1);
|
|
it++;
|
|
return it;
|
|
}
|
|
|
|
int End() const
|
|
{
|
|
return GetNBags();
|
|
}
|
|
|
|
void GetData (const Iterator & it,
|
|
INDEX_3 & ahash, T & acont) const
|
|
{
|
|
ahash = hash[it.BagNr()][it.Pos()];
|
|
acont = cont[it.BagNr()][it.Pos()];
|
|
}
|
|
|
|
const INDEX_3 & GetHash (const Iterator & it) const
|
|
{ return hash[it.BagNr()][it.Pos()]; }
|
|
|
|
const T & GetData (const Iterator & it) const
|
|
{ return cont[it.BagNr()][it.Pos()]; }
|
|
|
|
|
|
void DoArchive (Archive & ar)
|
|
{
|
|
ar & hash & cont;
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
template <typename T>
|
|
inline ostream & operator<< (ostream & ost, const INDEX_3_HASHTABLE<T> & ht)
|
|
{
|
|
for (typename INDEX_3_HASHTABLE<T>::Iterator it = ht.Begin();
|
|
it != ht.End(); it++)
|
|
{
|
|
ost << ht.GetHash(it) << ": " << ht.GetData(it) << endl;
|
|
}
|
|
|
|
return ost;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Closed Hashing HT
|
|
|
|
class BASE_INDEX_CLOSED_HASHTABLE
|
|
{
|
|
protected:
|
|
///
|
|
// MoveableArray<INDEX> hash;
|
|
NgArray<INDEX> hash;
|
|
///
|
|
int invalid;
|
|
public:
|
|
///
|
|
BASE_INDEX_CLOSED_HASHTABLE (int size);
|
|
|
|
int Size() const { return hash.Size(); }
|
|
int UsedPos (int pos) const { return ! (hash.Get(pos) == invalid); }
|
|
int UsedElements () const;
|
|
|
|
///
|
|
int HashValue (const INDEX & ind) const
|
|
{
|
|
return (3*ind) % hash.Size() + 1;
|
|
}
|
|
|
|
|
|
int Position (const INDEX & ind) const
|
|
{
|
|
int i = HashValue(ind);
|
|
while (1)
|
|
{
|
|
if (hash.Get(i) == ind) return i;
|
|
if (hash.Get(i) == invalid) return 0;
|
|
i++;
|
|
if (i > hash.Size()) i = 1;
|
|
}
|
|
}
|
|
|
|
int CalcPositionCosts (const INDEX & ind) const
|
|
{
|
|
int i = HashValue(ind);
|
|
int costs = 1;
|
|
while (1)
|
|
{
|
|
if (hash.Get(i) == ind) return costs;
|
|
if (hash.Get(i) == invalid) return costs;
|
|
i++;
|
|
if (i > hash.Size()) i = 1;
|
|
costs++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// returns 1, if new position is created
|
|
int PositionCreate (const INDEX & ind, int & apos)
|
|
{
|
|
int i = HashValue (ind);
|
|
if (hash.Get(i) == ind)
|
|
{
|
|
apos = i;
|
|
return 0;
|
|
}
|
|
if (hash.Get(i) == invalid)
|
|
{
|
|
hash.Elem(i) = ind;
|
|
apos = i;
|
|
return 1;
|
|
}
|
|
return PositionCreate2 (ind, apos);
|
|
}
|
|
|
|
protected:
|
|
int Position2 (const INDEX & ind) const;
|
|
int PositionCreate2 (const INDEX & ind, int & apos);
|
|
void BaseSetSize (int asize);
|
|
};
|
|
|
|
|
|
template <class T>
|
|
class INDEX_CLOSED_HASHTABLE : public BASE_INDEX_CLOSED_HASHTABLE
|
|
{
|
|
///
|
|
// MoveableArray<T> cont;
|
|
NgArray<T> cont;
|
|
|
|
public:
|
|
///
|
|
INDEX_CLOSED_HASHTABLE (int size)
|
|
: BASE_INDEX_CLOSED_HASHTABLE(size), cont(size)
|
|
{
|
|
; // cont.SetName ("ind-hashtable, contents");
|
|
}
|
|
|
|
|
|
void Set (const INDEX & ahash, const T & acont)
|
|
{
|
|
int pos;
|
|
PositionCreate (ahash, pos);
|
|
hash.Elem(pos) = ahash;
|
|
cont.Elem(pos) = acont;
|
|
}
|
|
|
|
const T & Get (const INDEX & ahash) const
|
|
{
|
|
int pos = Position (ahash);
|
|
return cont.Get(pos);
|
|
}
|
|
|
|
///
|
|
bool Used (const INDEX & ahash) const
|
|
{
|
|
int pos = Position (ahash);
|
|
return (pos != 0);
|
|
}
|
|
|
|
|
|
///
|
|
inline void SetData (int pos, const INDEX & ahash, const T & acont)
|
|
{
|
|
hash.Elem(pos) = ahash;
|
|
cont.Elem(pos) = acont;
|
|
}
|
|
|
|
///
|
|
void GetData (int pos, INDEX & ahash, T & acont) const
|
|
{
|
|
ahash = hash.Get(pos);
|
|
acont = cont.Get(pos);
|
|
}
|
|
|
|
///
|
|
inline void SetData (int pos, const T & acont)
|
|
{
|
|
cont.Elem(pos) = acont;
|
|
}
|
|
|
|
///
|
|
void GetData (int pos, T & acont) const
|
|
{
|
|
acont = cont.Get(pos);
|
|
}
|
|
|
|
///
|
|
const T & GetData (int pos) { return cont.Get(pos); }
|
|
///
|
|
inline void SetSize (int size)
|
|
{
|
|
BaseSetSize(size);
|
|
cont.SetSize(size);
|
|
}
|
|
|
|
///
|
|
inline void DeleteData ()
|
|
{ SetSize (cont.Size()); }
|
|
|
|
void SetName (const char * aname)
|
|
{
|
|
// cont.SetName(aname);
|
|
// hash.SetName(aname);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
inline size_t RoundUp2 (size_t i)
|
|
{
|
|
size_t res = 1;
|
|
while (res < i) res *= 2; // hope it will never be too large
|
|
return res;
|
|
}
|
|
|
|
/// Closed Hashing HT
|
|
|
|
class BASE_INDEX_2_CLOSED_HASHTABLE
|
|
{
|
|
protected:
|
|
///
|
|
// MoveableArray<INDEX_2> hash;
|
|
NgArray<INDEX_2> hash;
|
|
///
|
|
int invalid;
|
|
size_t mask;
|
|
public:
|
|
///
|
|
BASE_INDEX_2_CLOSED_HASHTABLE (size_t size);
|
|
|
|
int Size() const { return hash.Size(); }
|
|
bool UsedPos0 (int pos) const { return ! (hash[pos].I1() == invalid); }
|
|
int UsedElements () const;
|
|
|
|
///
|
|
int HashValue (const INDEX_2 & ind) const
|
|
{
|
|
// return (ind.I1() + 71 * ind.I2()) % hash.Size() + 1;
|
|
return (ind.I1() + 71 * ind.I2()) & mask;
|
|
}
|
|
|
|
|
|
int Position0 (const INDEX_2 & ind) const
|
|
{
|
|
int i = HashValue(ind);
|
|
while (1)
|
|
{
|
|
if (hash[i] == ind) return i;
|
|
if (hash[i].I1() == invalid) return -1;
|
|
i = (i+1) & mask;
|
|
/*
|
|
i++;
|
|
if (i > hash.Size()) i = 1;
|
|
*/
|
|
}
|
|
}
|
|
|
|
// returns 1, if new position is created
|
|
bool PositionCreate0 (const INDEX_2 & ind, int & apos)
|
|
{
|
|
int i = HashValue (ind);
|
|
if (hash[i] == ind)
|
|
{
|
|
apos = i;
|
|
return false;
|
|
}
|
|
if (hash[i].I1() == invalid)
|
|
{
|
|
hash[i] = ind;
|
|
apos = i;
|
|
return true;
|
|
}
|
|
return PositionCreate2 (ind, apos);
|
|
}
|
|
|
|
protected:
|
|
///
|
|
|
|
int Position2 (const INDEX_2 & ind) const;
|
|
bool PositionCreate2 (const INDEX_2 & ind, int & apos);
|
|
void BaseSetSize (int asize);
|
|
};
|
|
|
|
|
|
template <class T>
|
|
class INDEX_2_CLOSED_HASHTABLE : public BASE_INDEX_2_CLOSED_HASHTABLE
|
|
{
|
|
NgArray<T> cont;
|
|
public:
|
|
INDEX_2_CLOSED_HASHTABLE (size_t size)
|
|
: BASE_INDEX_2_CLOSED_HASHTABLE(size), cont(RoundUp2(size))
|
|
{ ; }
|
|
|
|
void Set (const INDEX_2 & ahash, const T & acont)
|
|
{
|
|
int pos;
|
|
PositionCreate0 (ahash, pos);
|
|
hash[pos] = ahash;
|
|
cont[pos] = acont;
|
|
}
|
|
|
|
const T & Get (const INDEX_2 & ahash) const
|
|
{
|
|
int pos = Position0 (ahash);
|
|
return cont[pos];
|
|
}
|
|
|
|
inline bool Used (const INDEX_2 & ahash) const
|
|
{
|
|
int pos = Position0 (ahash);
|
|
return (pos != -1);
|
|
}
|
|
|
|
inline void SetData0 (int pos, const INDEX_2 & ahash, const T & acont)
|
|
{
|
|
hash[pos] = ahash;
|
|
cont[pos] = acont;
|
|
}
|
|
|
|
///
|
|
inline void GetData0 (int pos, INDEX_2 & ahash, T & acont) const
|
|
{
|
|
ahash = hash[pos];
|
|
acont = cont[pos];
|
|
}
|
|
|
|
inline void SetData0 (int pos, const T & acont)
|
|
{
|
|
cont[pos] = acont;
|
|
}
|
|
|
|
inline void GetData0 (int pos, T & acont) const
|
|
{
|
|
acont = cont[pos];
|
|
}
|
|
|
|
///
|
|
const T & GetData0 (int pos) { return cont[pos]; }
|
|
///
|
|
inline void SetSize (size_t size)
|
|
{
|
|
BaseSetSize(size);
|
|
cont.SetSize(RoundUp2(size));
|
|
}
|
|
|
|
|
|
///
|
|
inline void PrintMemInfo (ostream & ost) const;
|
|
///
|
|
inline void DeleteData ()
|
|
{ SetSize (cont.Size()); }
|
|
|
|
void SetName (const char * aname)
|
|
{
|
|
;
|
|
// cont.SetName(aname);
|
|
// hash.SetName(aname);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
inline ostream & operator<< (ostream & ost, const INDEX_2_CLOSED_HASHTABLE<T> & ht)
|
|
{
|
|
for (int i = 0; i < ht.Size(); i++)
|
|
if (ht.UsedPos(i))
|
|
{
|
|
INDEX_2 hash;
|
|
T data;
|
|
ht.GetData0 (i, hash, data);
|
|
ost << "hash = " << hash << ", data = " << data << endl;
|
|
}
|
|
return ost;
|
|
}
|
|
|
|
|
|
|
|
|
|
class BASE_INDEX_3_CLOSED_HASHTABLE
|
|
{
|
|
protected:
|
|
NgArray<INDEX_3> hash;
|
|
int invalid;
|
|
size_t mask;
|
|
|
|
protected:
|
|
BASE_INDEX_3_CLOSED_HASHTABLE (size_t size)
|
|
: hash(RoundUp2(size))
|
|
{
|
|
// cout << "orig size = " << size
|
|
// << ", roundup size = " << hash.Size();
|
|
size = hash.Size();
|
|
mask = size-1;
|
|
// cout << "mask = " << mask << endl;
|
|
invalid = -1;
|
|
for (size_t i = 0; i < size; i++)
|
|
hash[i].I1() = invalid;
|
|
}
|
|
|
|
public:
|
|
int Size() const
|
|
{
|
|
return hash.Size();
|
|
}
|
|
|
|
bool UsedPos (int pos) const
|
|
{
|
|
return ! (hash[pos].I1() == invalid);
|
|
}
|
|
|
|
int UsedElements () const
|
|
{
|
|
int n = hash.Size();
|
|
int cnt = 0;
|
|
for (int i = 0; i < n; i++)
|
|
if (hash[i].I1() != invalid)
|
|
cnt++;
|
|
return cnt;
|
|
}
|
|
|
|
int HashValue (const INDEX_3 & ind) const
|
|
{
|
|
// return (ind.I1() + 15 * ind.I2() + 41 * ind.I3()) % hash.Size();
|
|
return (ind.I1() + 15 * ind.I2() + 41 * ind.I3()) & mask;
|
|
}
|
|
|
|
int Position (const INDEX_3 & ind) const
|
|
{
|
|
int i = HashValue(ind);
|
|
while (1)
|
|
{
|
|
if (hash[i] == ind) return i;
|
|
if (hash[i].I1() == invalid) return -1;
|
|
// i = (i+1) % hash.Size();
|
|
i = (i+1) & mask;
|
|
}
|
|
}
|
|
|
|
int Costs (const INDEX_3 & ind) const
|
|
{
|
|
int i = HashValue(ind);
|
|
int c = 1;
|
|
while (1)
|
|
{
|
|
if (hash[i] == ind) return c;
|
|
if (hash[i].I1() == invalid) return c;
|
|
// i = (i+1) % hash.Size();
|
|
i = (i+1) & mask;
|
|
c++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// returns true, if new position is created
|
|
bool PositionCreate (const INDEX_3 & ind, int & apos)
|
|
{
|
|
int i = HashValue (ind);
|
|
if (hash[i] == ind)
|
|
{
|
|
apos = i;
|
|
return false;
|
|
}
|
|
if (hash[i].I1() == invalid)
|
|
{
|
|
hash[i] = ind;
|
|
apos = i;
|
|
return true;
|
|
}
|
|
return PositionCreate2 (ind, apos);
|
|
}
|
|
|
|
void DeleteData()
|
|
{
|
|
size_t size = hash.Size();
|
|
for (size_t i = 0; i < size; i++)
|
|
hash[i].I1() = invalid;
|
|
}
|
|
|
|
protected:
|
|
bool PositionCreate2 (const INDEX_3 & ind, int & apos);
|
|
void BaseSetSize (int asize);
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
class INDEX_3_CLOSED_HASHTABLE : public BASE_INDEX_3_CLOSED_HASHTABLE
|
|
{
|
|
// MoveableArray<T,0> cont;
|
|
NgArray<T,0> cont;
|
|
|
|
public:
|
|
INDEX_3_CLOSED_HASHTABLE (int size)
|
|
: BASE_INDEX_3_CLOSED_HASHTABLE(size), cont(RoundUp2(size))
|
|
{
|
|
; //cont.SetName ("i3-hashtable, contents");
|
|
}
|
|
|
|
void Set (const INDEX_3 & ahash, const T & acont)
|
|
{
|
|
int pos;
|
|
PositionCreate (ahash, pos);
|
|
hash[pos] = ahash;
|
|
cont[pos] = acont;
|
|
}
|
|
|
|
const T & Get (const INDEX_3 & ahash) const
|
|
{
|
|
return cont[Position (ahash)];
|
|
}
|
|
|
|
bool Used (const INDEX_3 & ahash) const
|
|
{
|
|
return (Position (ahash) != -1);
|
|
}
|
|
|
|
void SetData (int pos, const INDEX_3 & ahash, const T & acont)
|
|
{
|
|
hash[pos] = ahash;
|
|
cont[pos] = acont;
|
|
}
|
|
|
|
void GetData (int pos, INDEX_3 & ahash, T & acont) const
|
|
{
|
|
ahash = hash[pos];
|
|
acont = cont[pos];
|
|
}
|
|
|
|
void SetData (int pos, const T & acont)
|
|
{
|
|
cont[pos] = acont;
|
|
}
|
|
|
|
void GetData (int pos, T & acont) const
|
|
{
|
|
acont = cont[pos];
|
|
}
|
|
|
|
const T & GetData (int pos) const
|
|
{
|
|
return cont[pos];
|
|
}
|
|
|
|
void SetSize (int size)
|
|
{
|
|
BaseSetSize(size);
|
|
cont.SetSize(hash.Size());
|
|
}
|
|
|
|
void PrintMemInfo (ostream & ost) const
|
|
{
|
|
cout << "Hashtable: " << Size()
|
|
<< " entries of size " << sizeof(INDEX_3) << " + " << sizeof(T)
|
|
<< " = " << Size() * (sizeof(INDEX_3) + sizeof(T)) << " bytes" << endl;
|
|
|
|
}
|
|
|
|
void DeleteData ()
|
|
{
|
|
SetSize (cont.Size());
|
|
}
|
|
|
|
void SetName (const char * aname)
|
|
{
|
|
;
|
|
// cont.SetName(aname);
|
|
// hash.SetName(aname);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
inline ostream & operator<< (ostream & ost, const INDEX_3_CLOSED_HASHTABLE<T> & ht)
|
|
{
|
|
for (int i = 0; i < ht.Size(); i++)
|
|
if (ht.UsedPos(i))
|
|
{
|
|
INDEX_3 hash;
|
|
T data;
|
|
ht.GetData (i, hash, data);
|
|
ost << "hash = " << hash << ", data = " << data << endl;
|
|
}
|
|
return ost;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
inline INDEX_3_HASHTABLE<T> :: INDEX_3_HASHTABLE (int size)
|
|
: BASE_INDEX_3_HASHTABLE (size), cont(size)
|
|
{
|
|
;
|
|
}
|
|
|
|
template<class T>
|
|
inline int INDEX_3_HASHTABLE<T> :: PositionCreate (const INDEX_3 & ahash, int & bnr, int & colnr)
|
|
{
|
|
bnr = HashValue (ahash);
|
|
colnr = Position (bnr, ahash);
|
|
if (!colnr)
|
|
{
|
|
hash.Add (bnr, ahash);
|
|
cont.AddEmpty (bnr);
|
|
colnr = cont.EntrySize (bnr);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
template<class T>
|
|
inline void INDEX_3_HASHTABLE<T> :: Set (const INDEX_3 & ahash, const T & acont)
|
|
{
|
|
int bnr = HashValue (ahash);
|
|
int pos = Position (bnr, ahash);
|
|
if (pos)
|
|
cont.Set (bnr, pos, acont);
|
|
else
|
|
{
|
|
hash.Add1 (bnr, ahash);
|
|
cont.Add1 (bnr, acont);
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
inline const T & INDEX_3_HASHTABLE<T> :: Get (const INDEX_3 & ahash) const
|
|
{
|
|
int bnr = HashValue (ahash);
|
|
int pos = Position (bnr, ahash);
|
|
return cont.Get (bnr, pos);
|
|
}
|
|
|
|
template<class T>
|
|
inline bool INDEX_3_HASHTABLE<T> :: Used (const INDEX_3 & ahash) const
|
|
{
|
|
return (Position (HashValue (ahash), ahash)) ? 1 : 0;
|
|
}
|
|
|
|
template<class T>
|
|
inline int INDEX_3_HASHTABLE<T> :: GetNBags () const
|
|
{
|
|
return cont.Size();
|
|
}
|
|
|
|
template<class T>
|
|
inline int INDEX_3_HASHTABLE<T> :: GetBagSize (int bnr) const
|
|
{
|
|
return cont.EntrySize (bnr);
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_3_HASHTABLE<T> :: GetData (int bnr, int colnr, INDEX_3 & ahash, T & acont) const
|
|
{
|
|
ahash = hash.Get(bnr, colnr);
|
|
acont = cont.Get(bnr, colnr);
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_3_HASHTABLE<T> :: SetData (int bnr, int colnr, const INDEX_3 & ahash, const T & acont)
|
|
{
|
|
hash.Set(bnr, colnr, ahash);
|
|
cont.Set(bnr, colnr, acont);
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_3_HASHTABLE<T> :: SetSize (int size)
|
|
{
|
|
hash.SetSize (size);
|
|
cont.SetSize (size);
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_3_HASHTABLE<T> :: DeleteData ()
|
|
{
|
|
int n = hash.Size();
|
|
hash.SetSize (n);
|
|
cont.SetSize (n);
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_3_HASHTABLE<T> :: PrepareSet (const INDEX_3 & ahash)
|
|
{
|
|
int bnr = HashValue (ahash);
|
|
hash.IncSizePrepare (bnr-1);
|
|
cont.IncSizePrepare (bnr-1);
|
|
}
|
|
|
|
|
|
template<class T>
|
|
inline void INDEX_3_HASHTABLE<T> :: AllocateElements ()
|
|
{
|
|
hash.AllocateElementsOneBlock();
|
|
cont.AllocateElementsOneBlock();
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
inline void INDEX_3_HASHTABLE<T> :: PrintMemInfo (ostream & ost) const
|
|
{
|
|
ost << "Hash: " << endl;
|
|
hash.PrintMemInfo (ost);
|
|
ost << "Cont: " << endl;
|
|
cont.PrintMemInfo (ost);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
inline INDEX_HASHTABLE<T> :: INDEX_HASHTABLE (int size)
|
|
: BASE_INDEX_HASHTABLE (size), cont(size)
|
|
{
|
|
;
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_HASHTABLE<T> :: Set (const INDEX & ahash, const T & acont)
|
|
{
|
|
int bnr = HashValue (ahash);
|
|
int pos = Position (bnr, ahash);
|
|
if (pos)
|
|
cont.Set (bnr, pos, acont);
|
|
else
|
|
{
|
|
hash.Add (bnr, ahash);
|
|
cont.Add (bnr, acont);
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
inline const T & INDEX_HASHTABLE<T> :: Get (const INDEX & ahash) const
|
|
{
|
|
int bnr = HashValue (ahash);
|
|
int pos = Position (bnr, ahash);
|
|
return cont.Get (bnr, pos);
|
|
}
|
|
|
|
template<class T>
|
|
inline bool INDEX_HASHTABLE<T> :: Used (const INDEX & ahash) const
|
|
{
|
|
return (Position (HashValue (ahash), ahash)) ? 1 : 0;
|
|
}
|
|
|
|
template<class T>
|
|
inline int INDEX_HASHTABLE<T> :: GetNBags () const
|
|
{
|
|
return hash.Size();
|
|
}
|
|
|
|
template<class T>
|
|
inline int INDEX_HASHTABLE<T> :: GetBagSize (int bnr) const
|
|
{
|
|
return hash.EntrySize(bnr);
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_HASHTABLE<T> :: GetData (int bnr, int colnr, INDEX & ahash, T & acont) const
|
|
{
|
|
ahash = hash.Get(bnr, colnr);
|
|
acont = cont.Get(bnr, colnr);
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_HASHTABLE<T> :: PrintMemInfo (ostream & ost) const
|
|
{
|
|
ost << "Hash: " << endl;
|
|
hash.PrintMemInfo (ost);
|
|
ost << "Cont: " << endl;
|
|
cont.PrintMemInfo (ost);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* *********** Closed Hashing ************************* */
|
|
|
|
template<class T>
|
|
inline void INDEX_2_CLOSED_HASHTABLE<T> ::
|
|
PrintMemInfo (ostream & ost) const
|
|
{
|
|
cout << "Hashtable: " << Size()
|
|
<< " entries of size " << sizeof(INDEX_2) << " + " << sizeof(T)
|
|
<< " = " << Size() * (sizeof(INDEX_2) + sizeof(T)) << " bytes."
|
|
<< " Used els: " << UsedElements()
|
|
<< endl;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
template<class T>
|
|
inline INDEX_3_CLOSED_HASHTABLE<T> ::
|
|
INDEX_3_CLOSED_HASHTABLE (int size)
|
|
: BASE_INDEX_3_CLOSED_HASHTABLE(size), cont(size)
|
|
{
|
|
cont.SetName ("i3-hashtable, contents");
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_3_CLOSED_HASHTABLE<T> ::
|
|
Set (const INDEX_3 & ahash, const T & acont)
|
|
{
|
|
int pos;
|
|
PositionCreate (ahash, pos);
|
|
hash.Elem(pos) = ahash;
|
|
cont.Elem(pos) = acont;
|
|
}
|
|
|
|
template<class T>
|
|
inline const T & INDEX_3_CLOSED_HASHTABLE<T> ::
|
|
Get (const INDEX_3 & ahash) const
|
|
{
|
|
int pos = Position (ahash);
|
|
return cont[pos];
|
|
}
|
|
|
|
template<class T>
|
|
inline bool INDEX_3_CLOSED_HASHTABLE<T> ::
|
|
Used (const INDEX_3 & ahash) const
|
|
{
|
|
int pos = Position (ahash);
|
|
return (pos != 0);
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_3_CLOSED_HASHTABLE<T> ::
|
|
SetData (int pos, const INDEX_3 & ahash, const T & acont)
|
|
{
|
|
hash.Elem(pos) = ahash;
|
|
cont.Elem(pos) = acont;
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_3_CLOSED_HASHTABLE<T> ::
|
|
GetData (int pos, INDEX_3 & ahash, T & acont) const
|
|
{
|
|
ahash = hash.Get(pos);
|
|
acont = cont.Get(pos);
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_3_CLOSED_HASHTABLE<T> ::
|
|
SetData (int pos, const T & acont)
|
|
{
|
|
cont.Elem(pos) = acont;
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_3_CLOSED_HASHTABLE<T> ::
|
|
GetData (int pos, T & acont) const
|
|
{
|
|
acont = cont.Get(pos);
|
|
}
|
|
|
|
template<class T>
|
|
inline const T & INDEX_3_CLOSED_HASHTABLE<T> ::
|
|
GetData (int pos) const
|
|
{
|
|
return cont.Get(pos);
|
|
}
|
|
|
|
|
|
template<class T>
|
|
inline void INDEX_3_CLOSED_HASHTABLE<T> ::
|
|
SetSize (int size)
|
|
{
|
|
BaseSetSize(size);
|
|
cont.SetSize(size);
|
|
}
|
|
|
|
template<class T>
|
|
inline void INDEX_3_CLOSED_HASHTABLE<T> ::
|
|
PrintMemInfo (ostream & ost) const
|
|
{
|
|
cout << "Hashtable: " << Size()
|
|
<< " entries of size " << sizeof(INDEX_3) << " + " << sizeof(T)
|
|
<< " = " << Size() * (sizeof(INDEX_3) + sizeof(T)) << " bytes" << endl;
|
|
}
|
|
*/
|
|
|
|
|
|
inline void SetInvalid (INDEX & i) { i = -1; }
|
|
inline bool IsInvalid (INDEX i) { return i == -1; }
|
|
inline size_t HashValue (INDEX i, size_t size) { return (113*size_t(i)) % size; }
|
|
|
|
inline void SetInvalid (INDEX_2 & i2) { i2[0] = -1; }
|
|
inline bool IsInvalid (INDEX_2 i2) { return i2[0] == -1; }
|
|
inline size_t HashValue (INDEX_2 i2, size_t size) { return (113*size_t(i2[0])+size_t(i2[1])) % size; }
|
|
|
|
inline void SetInvalid (INDEX_3 & i3) { i3[0] = -1; }
|
|
inline bool IsInvalid (INDEX_3 i3) { return i3[0] == -1; }
|
|
inline size_t HashValue (INDEX_3 i3, size_t size) { return (i3[0]+15*size_t(i3[1])+41*size_t(i3[2])) % size; }
|
|
|
|
|
|
/**
|
|
A closed hash-table.
|
|
All information is stored in one fixed array.
|
|
The array should be allocated with the double size of the expected number of entries.
|
|
*/
|
|
template <class T_HASH, class T>
|
|
class ClosedHashTable
|
|
{
|
|
protected:
|
|
///
|
|
size_t size;
|
|
///
|
|
size_t used;
|
|
///
|
|
NgArray<T_HASH> hash;
|
|
///
|
|
NgArray<T> cont;
|
|
public:
|
|
///
|
|
ClosedHashTable (size_t asize = 128)
|
|
: size(asize), used(0), hash(asize), cont(asize)
|
|
{
|
|
for (auto & v : hash)
|
|
SetInvalid(v);
|
|
}
|
|
|
|
ClosedHashTable (ClosedHashTable && ht2) = default;
|
|
|
|
ClosedHashTable (NgFlatArray<T_HASH> _hash, NgFlatArray<T> _cont)
|
|
: size(_hash.Size()), used(0), hash(_hash.Size(), _hash.Addr(0)), cont(_cont.Size(), _cont.Addr(0))
|
|
{
|
|
for (auto & v : hash)
|
|
SetInvalid(v);
|
|
}
|
|
|
|
|
|
ClosedHashTable & operator= (ClosedHashTable && ht2) = default;
|
|
|
|
///
|
|
size_t Size() const
|
|
{
|
|
return size;
|
|
}
|
|
|
|
/// is position used
|
|
bool UsedPos (size_t pos) const
|
|
{
|
|
return ! (IsInvalid(hash[pos]));
|
|
}
|
|
|
|
/// number of used elements
|
|
size_t UsedElements () const
|
|
{
|
|
return used;
|
|
}
|
|
|
|
size_t Position (const T_HASH ind) const
|
|
{
|
|
size_t i = HashValue(ind, size);
|
|
while (1)
|
|
{
|
|
if (hash[i] == ind) return i;
|
|
if (IsInvalid(hash[i])) return size_t(-1);
|
|
i++;
|
|
if (i >= size) i = 0;
|
|
}
|
|
}
|
|
|
|
void DoubleSize()
|
|
{
|
|
ClosedHashTable tmp(2*Size());
|
|
for (auto both : *this)
|
|
tmp[both.first] = both.second;
|
|
*this = move(tmp);
|
|
}
|
|
|
|
// returns true if new position is created
|
|
bool PositionCreate (const T_HASH ind, size_t & apos)
|
|
{
|
|
if (UsedElements()*2 > Size()) DoubleSize();
|
|
|
|
size_t i = HashValue (ind, size);
|
|
|
|
while (1)
|
|
{
|
|
if (IsInvalid(hash[i]))
|
|
{
|
|
hash[i] = ind;
|
|
apos = i;
|
|
used++;
|
|
return true;
|
|
}
|
|
if (hash[i] == ind)
|
|
{
|
|
apos = i;
|
|
return false;
|
|
}
|
|
i++;
|
|
if (i >= size) i = 0;
|
|
}
|
|
}
|
|
|
|
|
|
///
|
|
void Set (const T_HASH & ahash, const T & acont)
|
|
{
|
|
size_t pos;
|
|
PositionCreate (ahash, pos);
|
|
hash[pos] = ahash;
|
|
cont[pos] = acont;
|
|
}
|
|
|
|
///
|
|
const T & Get (const T_HASH & ahash) const
|
|
{
|
|
size_t pos = Position (ahash);
|
|
if (pos == size_t(-1))
|
|
throw Exception (string("illegal key: ") + ToString(ahash) );
|
|
return cont[pos];
|
|
}
|
|
|
|
///
|
|
bool Used (const T_HASH & ahash) const
|
|
{
|
|
return (Position (ahash) != size_t(-1));
|
|
}
|
|
|
|
void SetData (size_t pos, const T_HASH & ahash, const T & acont)
|
|
{
|
|
hash[pos] = ahash;
|
|
cont[pos] = acont;
|
|
}
|
|
|
|
void GetData (size_t pos, T_HASH & ahash, T & acont) const
|
|
{
|
|
ahash = hash[pos];
|
|
acont = cont[pos];
|
|
}
|
|
|
|
void SetData (size_t pos, const T & acont)
|
|
{
|
|
cont[pos] = acont;
|
|
}
|
|
|
|
void GetData (size_t pos, T & acont) const
|
|
{
|
|
acont = cont[pos];
|
|
}
|
|
|
|
pair<T_HASH,T> GetBoth (size_t pos) const
|
|
{
|
|
return pair<T_HASH,T> (hash[pos], cont[pos]);
|
|
}
|
|
|
|
const T & operator[] (T_HASH key) const { return Get(key); }
|
|
T & operator[] (T_HASH key)
|
|
{
|
|
size_t pos;
|
|
PositionCreate(key, pos);
|
|
return cont[pos];
|
|
}
|
|
|
|
void SetSize (size_t asize)
|
|
{
|
|
size = asize;
|
|
hash.Alloc(size);
|
|
cont.Alloc(size);
|
|
|
|
// for (size_t i = 0; i < size; i++)
|
|
// hash[i] = invalid;
|
|
// hash = T_HASH(invalid);
|
|
for (auto & v : hash)
|
|
SetInvalid(v);
|
|
}
|
|
|
|
void Delete (T_HASH key)
|
|
{
|
|
size_t pos = Position(key);
|
|
if (pos == size_t(-1)) return;
|
|
SetInvalid (hash[pos]); used--;
|
|
|
|
while (1)
|
|
{
|
|
size_t nextpos = pos+1;
|
|
if (nextpos == size) nextpos = 0;
|
|
if (IsInvalid(hash[nextpos])) break;
|
|
|
|
auto key = hash[nextpos];
|
|
auto val = cont[nextpos];
|
|
SetInvalid (hash[nextpos]); used--;
|
|
|
|
Set (key, val);
|
|
pos = nextpos;
|
|
}
|
|
}
|
|
|
|
void DeleteData()
|
|
{
|
|
for (auto & v : hash)
|
|
SetInvalid(v);
|
|
used = 0;
|
|
}
|
|
|
|
class Iterator
|
|
{
|
|
const ClosedHashTable & tab;
|
|
size_t nr;
|
|
public:
|
|
Iterator (const ClosedHashTable & _tab, size_t _nr)
|
|
: tab(_tab), nr(_nr)
|
|
{
|
|
while (nr < tab.Size() && !tab.UsedPos(nr)) nr++;
|
|
}
|
|
Iterator & operator++()
|
|
{
|
|
nr++;
|
|
while (nr < tab.Size() && !tab.UsedPos(nr)) nr++;
|
|
return *this;
|
|
}
|
|
bool operator!= (const Iterator & it2) { return nr != it2.nr; }
|
|
auto operator* () const
|
|
{
|
|
T_HASH hash;
|
|
T val;
|
|
tab.GetData(nr, hash,val);
|
|
return std::make_pair(hash,val);
|
|
}
|
|
};
|
|
|
|
Iterator begin() const { return Iterator(*this, 0); }
|
|
Iterator end() const { return Iterator(*this, Size()); }
|
|
};
|
|
|
|
template <class T_HASH, class T>
|
|
ostream & operator<< (ostream & ost,
|
|
const ClosedHashTable<T_HASH,T> & tab)
|
|
{
|
|
for (size_t i = 0; i < tab.Size(); i++)
|
|
if (tab.UsedPos(i))
|
|
{
|
|
T_HASH key;
|
|
T val;
|
|
tab.GetData (i, key, val);
|
|
ost << key << ": " << val << ", ";
|
|
}
|
|
return ost;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|