## Public API Reference

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# csutil/hash.h

Go to the documentation of this file.

    00001 /*
    00002     Copyright (C) 2003 by Mat Sutcliffe <oktal@gmx.co.uk>
    00003
    00004     This library is free software; you can redistribute it and/or
    00005     modify it under the terms of the GNU Lesser General Public
    00006     License as published by the Free Software Foundation; either
    00007     version 2 of the License, or (at your option) any later version.
    00008
    00009     This library is distributed in the hope that it will be useful,
    00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00012     Library General Public License for more details.
    00013
    00014     You should have received a copy of the GNU Library General Public
    00015     License along with this library; if not, write to the Free
    00016     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    00017 */
    00018
    00019 #ifndef __CS_UTIL_HASH_H__
    00020 #define __CS_UTIL_HASH_H__
    00021
    00026 #include "csextern.h"
    00027 #include "csutil/array.h"
    00028 #include "csutil/comparator.h"
    00029 #include "csutil/util.h"
    00030
    00031
    00041 CS_CRYSTALSPACE_EXPORT unsigned int csHashCompute (char const*);
    00042
    00049 CS_CRYSTALSPACE_EXPORT unsigned int csHashCompute (char const*, size_t length);
    00050
    00055 template <class T>
    00056 class csHashComputer
    00057 {
    00058 public:
    00060   static uint ComputeHash (const T& key)
    00061   {
    00062     return key.GetHash();
    00063   }
    00064 };
    00065
    00070 template <class T>
    00071 class csHashComputerIntegral
    00072 {
    00073 public:
    00075   static uint ComputeHash (const T& key)
    00076   {
    00077     return (uintptr_t)key;
    00078   }
    00079 };
    00080
    00082
    00085 template<>
    00086 class csHashComputer<void*> : public csHashComputerIntegral<void*> {};
    00087
    00088 template<>
    00089 class csHashComputer<int> : public csHashComputerIntegral<int> {};
    00090 template<>
    00091 class csHashComputer<unsigned int> :
    00092   public csHashComputerIntegral<unsigned int> {};
    00093
    00094 template<>
    00095 class csHashComputer<long> : public csHashComputerIntegral<long> {};
    00096 template<>
    00097 class csHashComputer<unsigned long> :
    00098   public csHashComputerIntegral<unsigned long> {};
    00099
    00100 #if (CS_LONG_SIZE < 8)
    00101 template<>
    00102 class csHashComputer<longlong> :
    00103   public csHashComputerIntegral<longlong> {};
    00104 template<>
    00105 class csHashComputer<ulonglong> :
    00106   public csHashComputerIntegral<ulonglong> {};
    00107 #endif
    00108
    00109 template<>
    00110 class csHashComputer<float>
    00111 {
    00112 public:
    00114   static uint ComputeHash (float key)
    00115   {
    00116     union
    00117     {
    00118       float f;
    00119       uint u;
    00120     } float2uint;
    00121     float2uint.f = key;
    00122     return float2uint.u;
    00123   }
    00124 };
    00125 template<>
    00126 class csHashComputer<double>
    00127 {
    00128 public:
    00130   static uint ComputeHash (double key)
    00131   {
    00132     union
    00133     {
    00134       double f;
    00135       uint u;
    00136     } double2uint;
    00137     double2uint.f = key;
    00138     return double2uint.u;
    00139   }
    00140 };
    00142
    00146 template <typename T>
    00147 class csPtrKey
    00148 {
    00149   T* ptr;
    00150 public:
    00151   csPtrKey () : ptr(0) {}
    00152   csPtrKey (T* ptr) : ptr(ptr) {}
    00153   csPtrKey (csPtrKey const& other) : ptr (other.ptr) {}
    00154
    00155   uint GetHash () const { return (uintptr_t)ptr; }
    00156   inline friend bool operator < (const csPtrKey& r1, const csPtrKey& r2)
    00157   { return r1.ptr < r2.ptr; }
    00158   operator T* () const
    00159   { return ptr; }
    00160   T* operator -> () const
    00161   { return ptr; }
    00162   csPtrKey& operator = (csPtrKey const& other)
    00163   { ptr = other.ptr; return *this; }
    00164 };
    00165
    00175 template <class T>
    00176 class csHashComputerString
    00177 {
    00178 public:
    00179   static uint ComputeHash (const T& key)
    00180   {
    00181     return csHashCompute ((const char*)key);
    00182   }
    00183 };
    00184
    00188 template<>
    00189 class csHashComputer<const char*> : public csHashComputerString<const char*> {};
    00190
    00200 template <class T>
    00201 class csHashComputerStruct
    00202 {
    00203 public:
    00204   static uint ComputeHash (const T& key)
    00205   {
    00206     return csHashCompute ((char*)&key, sizeof (T));
    00207   }
    00208 };
    00209
    00210 #include "csutil/win32/msvc_deprecated_warn_off.h"
    00211
    00217 class CS_DEPRECATED_TYPE_MSG("csString can also be used for hash keys")
    00218   csStrKey
    00219 {
    00220 private:
    00221   char* str;
    00222
    00223 public:
    00224   csStrKey () { str = 0; }
    00225   csStrKey (const char* s) { str = csStrNew (s); }
    00226   csStrKey (const csStrKey& c) { str = csStrNew (c.str); }
    00227   ~csStrKey () { delete[] str; }
    00228   csStrKey& operator=(const csStrKey& o)
    00229   {
    00230     delete[] str; str = csStrNew (o.str);
    00231     return *this;
    00232   }
    00233   operator const char* () const { return str; }
    00234   uint GetHash() const { return csHashCompute (str); }
    00235 };
    00236
    00240 template<>
    00241 class csComparator<csStrKey, csStrKey> : public csComparatorString<csStrKey> {};
    00242
    00243 #include "csutil/win32/msvc_deprecated_warn_on.h"
    00244
    00254 template <class T, class K = unsigned int,
    00255   class ArrayMemoryAlloc = CS::Memory::AllocatorMalloc>
    00256 class csHash
    00257 {
    00258 protected:
    00259   struct Element
    00260   {
    00261     const K key;
    00262     T value;
    00263
    00264     Element (const K& key0, const T &value0) : key (key0), value (value0) {}
    00265     Element (const Element &other) : key (other.key), value (other.value) {}
    00266   };
    00267   typedef csArray<Element, csArrayElementHandler<Element>,
    00268     ArrayMemoryAlloc> ElementArray;
    00269   csArray<ElementArray, csArrayElementHandler<ElementArray>,
    00270     ArrayMemoryAlloc> Elements;
    00271
    00272   size_t Modulo;
    00273
    00274 private:
    00275   size_t InitModulo;
    00276   size_t GrowRate;
    00277   size_t MaxSize;
    00278   size_t Size;
    00279
    00280   void Grow ()
    00281   {
    00282     static const size_t Primes[] =
    00283     {
    00284       53,         97,         193,       389,       769,
    00285       1543,       3079,       6151,      12289,     24593,
    00286       49157,      98317,      196613,    393241,    786433,
    00287       1572869,    3145739,    6291469,   12582917,  25165843,
    00288       50331653,   100663319,  201326611, 402653189, 805306457,
    00289       1610612741, 0
    00290     };
    00291
    00292     const size_t *p;
    00293     size_t elen = Elements.Length ();
    00294     for (p = Primes; *p && *p <= elen; p++) ;
    00295     Modulo = *p;
    00296     CS_ASSERT (Modulo);
    00297
    00298     Elements.SetLength(Modulo, ElementArray (0, MIN(Modulo / GrowRate, 4)));
    00299
    00300     for (size_t i = 0; i < elen; i++)
    00301     {
    00302       ElementArray& src = Elements[i];
    00303       size_t slen = src.Length ();
    00304       for (size_t j = slen; j > 0; j--)
    00305       {
    00306         const Element& srcElem = src[j - 1];
    00307         ElementArray& dst =
    00308           Elements.Get (csHashComputer<K>::ComputeHash (srcElem.key) % Modulo);
    00309         if (&src != &dst)
    00310         {
    00311           dst.Push (srcElem);
    00312           src.DeleteIndex (j - 1);
    00313         }
    00314       }
    00315     }
    00316   }
    00317
    00318 public:
    00333   csHash (size_t size = 23, size_t grow_rate = 5, size_t max_size = 20000)
    00334     : Modulo (size), InitModulo (size),
    00335       GrowRate (MIN (grow_rate, size)), MaxSize (max_size), Size (0)
    00336   {
    00337   }
    00338
    00340   csHash (const csHash<T> &o) : Elements (o.Elements),
    00341     Modulo (o.Modulo), InitModulo (o.InitModulo),
    00342     GrowRate (o.GrowRate), MaxSize (o.MaxSize), Size (o.Size) {}
    00343
    00351   void Put (const K& key, const T &value)
    00352   {
    00353     if (Elements.GetSize() == 0) Elements.SetLength (Modulo);
    00354     ElementArray& values =
    00355       Elements[csHashComputer<K>::ComputeHash (key) % Modulo];
    00356     values.Push (Element (key, value));
    00357     Size++;
    00358     if (values.Length () > Elements.Length () / GrowRate
    00359      && Elements.Length () < MaxSize) Grow ();
    00360   }
    00361
    00363   csArray<T> GetAll (const K& key) const
    00364   {
    00365     return GetAll<typename csArray<T>::ElementHandlerType,
    00366       typename csArray<T>::AllocatorType> (key);
    00367   }
    00368
    00370   template<typename H, typename M>
    00371   csArray<T, H, M> GetAll (const K& key) const
    00372   {
    00373     if (Elements.GetSize() == 0) return csArray<T> ();
    00374     const ElementArray& values =
    00375       Elements[csHashComputer<K>::ComputeHash (key) % Modulo];
    00376     csArray<T> ret (values.Length () / 2);
    00377     const size_t len = values.Length ();
    00378     for (size_t i = 0; i < len; ++i)
    00379     {
    00380       const Element& v = values[i];
    00381       if (csComparator<K, K>::Compare (v.key, key) == 0)
    00382         ret.Push (v.value);
    00383     }
    00384     return ret;
    00385   }
    00386
    00388   void PutUnique (const K& key, const T &value)
    00389   {
    00390     if (Elements.GetSize() == 0) Elements.SetLength (Modulo);
    00391     ElementArray& values =
    00392       Elements[csHashComputer<K>::ComputeHash (key) % Modulo];
    00393     const size_t len = values.Length ();
    00394     for (size_t i = 0; i < len; ++i)
    00395     {
    00396       Element& v = values[i];
    00397       if (csComparator<K, K>::Compare (v.key, key) == 0)
    00398       {
    00399         v.value = value;
    00400         return;
    00401       }
    00402     }
    00403
    00404     values.Push (Element (key, value));
    00405     Size++;
    00406     if (values.Length () > Elements.Length () / GrowRate
    00407      && Elements.Length () < MaxSize) Grow ();
    00408   }
    00409
    00414   CS_DEPRECATED_METHOD_MSG("Use PutUnique() instead.")
    00415   void PutFirst (const K& key, const T &value)
    00416   {
    00417     PutUnique(key, value);
    00418   }
    00419
    00421   bool Contains (const K& key) const
    00422   {
    00423     if (Elements.GetSize() == 0) return false;
    00424     const ElementArray& values =
    00425       Elements[csHashComputer<K>::ComputeHash (key) % Modulo];
    00426     const size_t len = values.Length ();
    00427     for (size_t i = 0; i < len; ++i)
    00428       if (csComparator<K, K>::Compare (values[i].key, key) == 0)
    00429         return true;
    00430     return false;
    00431   }
    00432
    00438   bool In (const K& key) const
    00439   { return Contains(key); }
    00440
    00445   const T* GetElementPointer (const K& key) const
    00446   {
    00447     if (Elements.GetSize() == 0) return 0;
    00448     const ElementArray& values =
    00449       Elements[csHashComputer<K>::ComputeHash (key) % Modulo];
    00450     const size_t len = values.Length ();
    00451     for (size_t i = 0; i < len; ++i)
    00452     {
    00453       const Element& v = values[i];
    00454       if (csComparator<K, K>::Compare (v.key, key) == 0)
    00455         return &v.value;
    00456     }
    00457
    00458     return 0;
    00459   }
    00460
    00465   T* GetElementPointer (const K& key)
    00466   {
    00467     if (Elements.GetSize() == 0) return 0;
    00468     ElementArray& values =
    00469       Elements[csHashComputer<K>::ComputeHash (key) % Modulo];
    00470     const size_t len = values.Length ();
    00471     for (size_t i = 0; i < len; ++i)
    00472     {
    00473       Element& v = values[i];
    00474       if (csComparator<K, K>::Compare (v.key, key) == 0)
    00475         return &v.value;
    00476     }
    00477
    00478     return 0;
    00479   }
    00480
    00485   const T& Get (const K& key, const T& fallback) const
    00486   {
    00487     if (Elements.GetSize() == 0) return fallback;
    00488     const ElementArray& values =
    00489       Elements[csHashComputer<K>::ComputeHash (key) % Modulo];
    00490     const size_t len = values.Length ();
    00491     for (size_t i = 0; i < len; ++i)
    00492     {
    00493       const Element& v = values[i];
    00494       if (csComparator<K, K>::Compare (v.key, key) == 0)
    00495         return v.value;
    00496     }
    00497
    00498     return fallback;
    00499   }
    00500
    00505   T& Get (const K& key, T& fallback)
    00506   {
    00507     if (Elements.GetSize() == 0) return fallback;
    00508     ElementArray& values =
    00509       Elements[csHashComputer<K>::ComputeHash (key) % Modulo];
    00510     const size_t len = values.Length ();
    00511     for (size_t i = 0; i < len; ++i)
    00512     {
    00513       Element& v = values[i];
    00514       if (csComparator<K, K>::Compare (v.key, key) == 0)
    00515         return v.value;
    00516     }
    00517
    00518     return fallback;
    00519   }
    00520
    00522   void DeleteAll ()
    00523   {
    00524     Elements.DeleteAll();
    00525     Modulo = InitModulo;
    00526     Size = 0;
    00527   }
    00528
    00530   void Empty() { DeleteAll(); }
    00531
    00533   bool DeleteAll (const K& key)
    00534   {
    00535     bool ret = false;
    00536     if (Elements.GetSize() == 0) return ret;
    00537     ElementArray& values =
    00538       Elements[csHashComputer<K>::ComputeHash (key) % Modulo];
    00539     for (size_t i = values.Length (); i > 0; i--)
    00540     {
    00541       const size_t idx = i - 1;
    00542       if (csComparator<K, K>::Compare (values[idx].key, key) == 0)
    00543       {
    00544         values.DeleteIndexFast (idx);
    00545         ret = true;
    00546         Size--;
    00547       }
    00548     }
    00549     return ret;
    00550   }
    00551
    00553   bool Delete (const K& key, const T &value)
    00554   {
    00555     bool ret = false;
    00556     if (Elements.GetSize() == 0) return ret;
    00557     ElementArray& values =
    00558       Elements[csHashComputer<K>::ComputeHash (key) % Modulo];
    00559     for (size_t i = values.Length (); i > 0; i--)
    00560     {
    00561       const size_t idx = i - 1;
    00562       if ((csComparator<K, K>::Compare (values[idx].key, key) == 0) &&
    00563           (csComparator<T, T>::Compare (values[idx].value, value) == 0 ))
    00564       {
    00565         values.DeleteIndexFast (idx);
    00566         ret = true;
    00567         Size--;
    00568       }
    00569     }
    00570     return ret;
    00571   }
    00572
    00574   size_t GetSize () const
    00575   {
    00576     return Size;
    00577   }
    00578
    00584   bool IsEmpty() const
    00585   {
    00586     return GetSize() == 0;
    00587   }
    00588
    00590   class Iterator
    00591   {
    00592   private:
    00593     csHash<T, K>* hash;
    00594     const K key;
    00595     size_t bucket, size, element;
    00596
    00597     void Seek ()
    00598     {
    00599       while ((element < size) &&
    00600         (csComparator<K, K>::Compare (hash->Elements[bucket][element].key,
    00601         key) != 0))
    00602           element++;
    00603     }
    00604
    00605   protected:
    00606     Iterator (csHash<T, K>* hash0, const K& key0) :
    00607       hash(hash0),
    00608       key(key0),
    00609       bucket(csHashComputer<K>::ComputeHash (key) % hash->Modulo),
    00610       size((hash->Elements.GetSize() > 0) ? hash->Elements[bucket].Length () : 0)
    00611       { Reset (); }
    00612
    00613     friend class csHash<T, K>;
    00614   public:
    00616     Iterator (const Iterator &o) :
    00617       hash (o.hash),
    00618       key(o.key),
    00619       bucket(o.bucket),
    00620       size(o.size),
    00621       element(o.element) {}
    00622
    00624     Iterator& operator=(const Iterator& o)
    00625     {
    00626       hash = o.hash;
    00627       key = o.key;
    00628       bucket = o.bucket;
    00629       size = o.size;
    00630       element = o.element;
    00631       return *this;
    00632     }
    00633
    00635     bool HasNext () const
    00636     {
    00637       return element < size;
    00638     }
    00639
    00641     T& Next ()
    00642     {
    00643       T &ret = hash->Elements[bucket][element].value;
    00644       element++;
    00645       Seek ();
    00646       return ret;
    00647     }
    00648
    00650     void Reset () { element = 0; Seek (); }
    00651   };
    00652   friend class Iterator;
    00653
    00655   class GlobalIterator
    00656   {
    00657   private:
    00658     csHash<T, K> *hash;
    00659     size_t bucket, size, element;
    00660
    00661     void Zero () { bucket = element = 0; }
    00662     void Init ()
    00663     {
    00664       size =
    00665         (hash->Elements.GetSize() > 0) ? hash->Elements[bucket].Length () : 0;
    00666     }
    00667
    00668     void FindItem ()
    00669     {
    00670       if (element >= size)
    00671       {
    00672         while (++bucket < hash->Elements.Length ())
    00673         {
    00674           Init ();
    00675           if (size != 0)
    00676           {
    00677             element = 0;
    00678             break;
    00679           }
    00680         }
    00681       }
    00682     }
    00683
    00684   protected:
    00685     GlobalIterator (csHash<T, K> *hash0) : hash (hash0)
    00686     {
    00687       Zero ();
    00688       Init ();
    00689       FindItem ();
    00690     }
    00691
    00692     friend class csHash<T, K>;
    00693   public:
    00695     GlobalIterator (const GlobalIterator &o) :
    00696       hash (o.hash),
    00697       bucket (o.bucket),
    00698       size (o.size),
    00699       element (o.element) {}
    00700
    00702     GlobalIterator& operator=(const GlobalIterator& o)
    00703     {
    00704       hash = o.hash;
    00705       bucket = o.bucket;
    00706       size = o.size;
    00707       element = o.element;
    00708       return *this;
    00709     }
    00710
    00712     bool HasNext () const
    00713     {
    00714       if (hash->Elements.Length () == 0) return false;
    00715       return element < size || bucket < hash->Elements.Length ();
    00716     }
    00717
    00719     void Advance ()
    00720     {
    00721       element++;
    00722       FindItem ();
    00723     }
    00724
    00726     T& NextNoAdvance ()
    00727     {
    00728       return hash->Elements[bucket][element].value;
    00729     }
    00730
    00732     T& Next ()
    00733     {
    00734       T &ret = NextNoAdvance ();
    00735       Advance ();
    00736       return ret;
    00737     }
    00738
    00740     T& NextNoAdvance (K &key)
    00741     {
    00742       key = hash->Elements[bucket][element].key;
    00743       return NextNoAdvance ();
    00744     }
    00745
    00747     T& Next (K &key)
    00748     {
    00749       key = hash->Elements[bucket][element].key;
    00750       return Next ();
    00751     }
    00752
    00754     void Reset () { Zero (); Init (); FindItem (); }
    00755   };
    00756   friend class GlobalIterator;
    00757
    00759   class ConstIterator
    00760   {
    00761   private:
    00762     const csHash<T, K>* hash;
    00763     const K key;
    00764     size_t bucket, size, element;
    00765
    00766     void Seek ()
    00767     {
    00768       while ((element < size) &&
    00769         (csComparator<K, K>::Compare (hash->Elements[bucket][element].key,
    00770         key) != 0))
    00771           element++;
    00772     }
    00773
    00774   protected:
    00775     ConstIterator (const csHash<T, K>* hash0, const K& key0) :
    00776       hash(hash0),
    00777       key(key0),
    00778       bucket(csHashComputer<K>::ComputeHash (key) % hash->Modulo),
    00779       size((hash->Elements.GetSize() > 0) ? hash->Elements[bucket].Length () : 0)
    00780       { Reset (); }
    00781
    00782     friend class csHash<T, K>;
    00783   public:
    00785     ConstIterator (const ConstIterator &o) :
    00786       hash (o.hash),
    00787       key(o.key),
    00788       bucket(o.bucket),
    00789       size(o.size),
    00790       element(o.element) {}
    00791
    00793     ConstIterator& operator=(const ConstIterator& o)
    00794     {
    00795       hash = o.hash;
    00796       key = o.key;
    00797       bucket = o.bucket;
    00798       size = o.size;
    00799       element = o.element;
    00800       return *this;
    00801     }
    00802
    00804     bool HasNext () const
    00805     {
    00806       return element < size;
    00807     }
    00808
    00810     const T& Next ()
    00811     {
    00812       const T &ret = hash->Elements[bucket][element].value;
    00813       element++;
    00814       Seek ();
    00815       return ret;
    00816     }
    00817
    00819     void Reset () { element = 0; Seek (); }
    00820   };
    00821   friend class ConstIterator;
    00822
    00824   class ConstGlobalIterator
    00825   {
    00826   private:
    00827     const csHash<T, K> *hash;
    00828     size_t bucket, size, element;
    00829
    00830     void Zero () { bucket = element = 0; }
    00831     void Init ()
    00832     {
    00833       size =
    00834         (hash->Elements.GetSize() > 0) ? hash->Elements[bucket].Length () : 0;
    00835     }
    00836
    00837     void FindItem ()
    00838     {
    00839       if (element >= size)
    00840       {
    00841         while (++bucket < hash->Elements.Length ())
    00842         {
    00843           Init ();
    00844           if (size != 0)
    00845           {
    00846             element = 0;
    00847             break;
    00848           }
    00849         }
    00850       }
    00851     }
    00852
    00853   protected:
    00854     ConstGlobalIterator (const csHash<T, K> *hash0) : hash (hash0)
    00855     {
    00856       Zero ();
    00857       Init ();
    00858       FindItem ();
    00859     }
    00860
    00861     friend class csHash<T, K>;
    00862   public:
    00864     ConstGlobalIterator (const ConstGlobalIterator &o) :
    00865       hash (o.hash),
    00866       bucket (o.bucket),
    00867       size (o.size),
    00868       element (o.element) {}
    00869
    00871     ConstGlobalIterator& operator=(const ConstGlobalIterator& o)
    00872     {
    00873       hash = o.hash;
    00874       bucket = o.bucket;
    00875       size = o.size;
    00876       element = o.element;
    00877       return *this;
    00878     }
    00879
    00881     bool HasNext () const
    00882     {
    00883       if (hash->Elements.Length () == 0) return false;
    00884       return element < size || bucket < hash->Elements.Length ();
    00885     }
    00886
    00888     void Advance ()
    00889     {
    00890       element++;
    00891       FindItem ();
    00892     }
    00893
    00895     const T& NextNoAdvance ()
    00896     {
    00897       return hash->Elements[bucket][element].value;
    00898     }
    00899
    00901     const T& Next ()
    00902     {
    00903       const T &ret = NextNoAdvance ();
    00904       Advance ();
    00905       return ret;
    00906     }
    00907
    00909     const T& NextNoAdvance (K &key)
    00910     {
    00911       key = hash->Elements[bucket][element].key;
    00912       return NextNoAdvance ();
    00913     }
    00914
    00916     const T& Next (K &key)
    00917     {
    00918       key = hash->Elements[bucket][element].key;
    00919       return Next ();
    00920     }
    00921
    00923     void Reset () { Zero (); Init (); FindItem (); }
    00924   };
    00925   friend class ConstGlobalIterator;
    00926
    00929   void DeleteElement (GlobalIterator& iterator)
    00930   {
    00931     Elements[iterator.bucket].DeleteIndex(iterator.element);
    00932     Size--;
    00933     iterator.size--;
    00934     iterator.FindItem ();
    00935   }
    00936
    00939   void DeleteElement (ConstGlobalIterator& iterator)
    00940   {
    00941     Elements[iterator.bucket].DeleteIndex(iterator.element);
    00942     Size--;
    00943     iterator.size--;
    00944     iterator.FindItem ();
    00945   }
    00946
    00953   Iterator GetIterator (const K& key)
    00954   {
    00955     return Iterator (this, key);
    00956   }
    00957
    00963   GlobalIterator GetIterator ()
    00964   {
    00965     return GlobalIterator (this);
    00966   }
    00967
    00974   ConstIterator GetIterator (const K& key) const
    00975   {
    00976     return ConstIterator (this, key);
    00977   }
    00978
    00984   ConstGlobalIterator GetIterator () const
    00985   {
    00986     return ConstGlobalIterator (this);
    00987   }
    00988 };
    00989
    00992 #endif