TCHashTable.h

Go to the documentation of this file.
00001 //*******************************************************************************
00002 //
00003 // *******   ***   ***               *
00004 //    *     *     *                  *
00005 //    *    *      *                *****
00006 //    *    *       ***  *   *   **   *    **    ***
00007 //    *    *          *  * *   *     *   ****  * * *
00008 //    *     *         *   *      *   * * *     * * *
00009 //    *      ***   ***    *     **   **   **   *   *
00010 //                        *
00011 //*******************************************************************************
00012 // see http://sourceforge.net/projects/tcsystem/ for details.
00013 // Copyright (C) 2003 - 2008 Thomas Goessler. All Rights Reserved. 
00014 //*******************************************************************************
00015 //
00016 // TCSystem is the legal property of its developers.
00017 // Please refer to the COPYRIGHT file distributed with this source distribution.
00018 // 
00019 // This library is free software; you can redistribute it and/or             
00020 // modify it under the terms of the GNU Lesser General Public                
00021 // License as published by the Free Software Foundation; either              
00022 // version 2.1 of the License, or (at your option) any later version.        
00023 //                                                                           
00024 // This library is distributed in the hope that it will be useful,           
00025 // but WITHOUT ANY WARRANTY; without even the implied warranty of            
00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         
00027 // Lesser General Public License for more details.                           
00028 //                                                                           
00029 // You should have received a copy of the GNU Lesser General Public          
00030 // License along with this library; if not, write to the Free Software       
00031 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
00032 //*******************************************************************************
00033 //  $Id: TCHashTable.h 801 2008-01-23 19:46:25Z the_____tiger $
00034 //*******************************************************************************
00035 
00036 #ifndef TC_HASHTABLE_H
00037 #define TC_HASHTABLE_H
00038 
00039 #include "TCTypes.h"
00040 
00041 #include <vector>
00042 #include <string>
00043 #include <functional>
00044 
00045 namespace TC
00046 {
00060    template <class KEY_TYPE> struct Hash { };
00061 
00063    template<> struct Hash<sint8>
00064    {
00065        uint32 operator() (sint8 val) const { return val; }
00066    };
00068    template<> struct Hash<uint8>
00069    {
00070        uint32 operator() (uint8 val) const { return val; }
00071    };
00073    template<> struct Hash<sint16>
00074    {
00075        uint32 operator() (sint16 val) const { return val; }
00076    };
00078    template<> struct Hash<uint16>
00079    {
00080        uint32 operator() (uint16 val) const { return val; }
00081    };
00083    template<> struct Hash<sint32>
00084    {
00085        uint32 operator() (sint32 val) const { return val; }
00086    };
00088    template<> struct Hash<uint32>
00089    {
00090        uint32 operator() (uint32 val) const { return val; }
00091    };
00092 
00094    template<> struct Hash<char*>
00095    {
00096        uint32 operator() (const char* text) const
00097        {
00098            const char *s = text;
00099            uint32 h=0;
00100            uint32 c;
00101            while((c=*s++) != '\0')
00102            {
00103                h = ((h << 5) + h) ^ c;
00104            }
00105            return h;
00106        }
00107    };
00108 
00110    template<> struct Hash<std::string>
00111    {
00112        uint32 operator() (const std::string& text) const
00113        {
00114            const char *s = text.c_str();
00115            uint32 h=0;
00116            uint32 c;
00117            while((c=*s++) != '\0')
00118            {
00119                h = ((h << 5) + h) ^ c;
00120            }
00121            return h;
00122        }
00123    };
00124 
00141    template< class KEY_TYPE,
00142              class MAP_TYPE=sint32,
00143              class HASH_FUNC=Hash< KEY_TYPE>,
00144              class KEY_VALUE_COMPARE_FUNC=std::equal_to<KEY_TYPE> >
00145    class HashTable
00146    {
00147    private:
00152        struct _Element
00153        {
00154            KEY_TYPE key_value;
00155            MAP_TYPE map_value;
00156        };
00157 
00158    public:
00165        HashTable(uint32 size, const MAP_TYPE& notFound)
00166            :m_size(size),
00167             m_not_found(notFound)
00168        {
00169            Clear();
00170        }
00171 
00173        virtual ~HashTable() {}
00174 
00176        inline uint32 GetHashSize() const { return m_size; }
00177 
00182        inline void SetHashSize(uint32 size)
00183        {
00184            m_size = size;
00185            Clear();
00186        }
00187 
00192        inline void Clear()
00193        {
00194            m_data.clear();
00195            m_data.reserve(m_size);
00196            for (uint32 i=0; i<m_size; i++)
00197            {
00198                m_data.push_back(std::vector< _Element >());
00199            }
00200        }
00201 
00206        inline const MAP_TYPE& GetNotFoundValue() const { return m_not_found; }
00207 
00212        inline void SetNotFoundValue(const MAP_TYPE& notFound) { m_not_found = notFound; }
00213 
00220        void AddKey(const KEY_TYPE &key_value, const MAP_TYPE& map_value)
00221        {
00222            uint32 p1;
00223            sint32 p2;
00224            GetElementPosition(key_value, p1, p2);
00225 
00226            _Element elem;
00227            elem.key_value = key_value;
00228            elem.map_value = map_value;
00229            if (p2 == -1)
00230            {
00231                m_data[p1].push_back(elem);
00232            }
00233            else
00234            {
00235                m_data[p1][p2] = elem;
00236            }
00237        }
00238 
00246        void RemoveKey(const KEY_TYPE &key_value)
00247        {
00248            uint32 p1;
00249            sint32 p2;
00250            GetElementPosition(key_value, p1, p2);
00251 
00252 
00253            if (p2 != -1)
00254            {
00255                m_data[p1].erase(m_data[p1].begin() + p2);
00256            }
00257        }
00258 
00266        const MAP_TYPE& GetMappedValue(const KEY_TYPE& key_value) const
00267        {
00268            uint32 p1;
00269            sint32 p2;
00270            GetElementPosition(key_value, p1, p2);
00271 
00272            if (p2 == -1)
00273            {
00274                return m_not_found;
00275            }
00276            else
00277            {
00278                return m_data[p1][p2].map_value;
00279            }
00280        }
00281 
00283        const MAP_TYPE& operator[](const KEY_TYPE& key_value) const { return GetMappedValue(key_value);}
00284 
00286        void GetAllKeys(std::vector< KEY_TYPE >& keys)
00287        {
00288            for (uint32 i=0; i<m_data.size(); i++)
00289            {
00290                for (uint32 j=0; j<m_data[i].size(); j++)
00291                {
00292                    keys.push_back(m_data[i][j].key_value);
00293                }
00294            }
00295        }
00296 
00298        void GetAllKeysAndValues(std::vector< KEY_TYPE >& keys, std::vector< MAP_TYPE >& values)
00299        {
00300            for (uint32 i=0; i<m_data.size(); i++)
00301            {
00302                for (uint32 j=0; j<m_data[i].size(); j++)
00303                {
00304                    keys.push_back(m_data[i][j].key_value);
00305                    values.push_back(m_data[i][j].map_value);
00306                }
00307            }
00308        }
00309 
00316        void GetStatistics(uint32& numEmptyLists, uint32& maxListLength, double& avgListLength) const
00317        {
00318            numEmptyLists = 0;
00319            maxListLength = 0;
00320            avgListLength = 0;
00321            for (uint32 i = 0; i < m_data.size(); i++)
00322            {
00323                uint32 thisListLength = m_data[i].size();
00324                if (thisListLength == 0) numEmptyLists++;
00325                if (maxListLength < thisListLength) maxListLength = thisListLength;
00326                avgListLength += thisListLength;
00327            }
00328            avgListLength /= m_data.size();
00329        }
00330 
00331    private:
00338        void GetElementPosition(const KEY_TYPE &key_value, uint32 &p1, sint32 &p2) const
00339        {
00340            KEY_VALUE_COMPARE_FUNC compare;
00341            p1 = GetTableEntryPosition(key_value);
00342            p2 = -1;
00343            for (uint32 i=0; i<m_data[p1].size(); i++)
00344            {
00345                if (compare(m_data[p1][i].key_value, key_value))
00346                {
00347                    p2 = i;
00348                    break;
00349                }
00350            }
00351        }
00352 
00361        uint32 GetTableEntryPosition(const KEY_TYPE &key_value) const
00362        {
00363            HASH_FUNC func;
00364            return (func(key_value) % m_size);
00365        }
00366 
00367    private:
00369        uint32 m_size;
00371        MAP_TYPE m_not_found;
00373        std::vector< std::vector< _Element > > m_data;
00374    };
00375 
00379 } // namespace TC
00380 
00381 #endif // TC_HASHTABLE_H

Copyright (c) Thomas Goessler 2003 - 2008