123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903 |
- #ifndef GIM_HASH_TABLE_H_INCLUDED
- #define GIM_HASH_TABLE_H_INCLUDED
- /*! \file gim_trimesh_data.h
- \author Francisco Leon Najera
- */
- /*
- -----------------------------------------------------------------------------
- This source file is part of GIMPACT Library.
- For the latest info, see http://gimpact.sourceforge.net/
- Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
- email: projectileman@yahoo.com
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
- -----------------------------------------------------------------------------
- */
- #include "gim_radixsort.h"
- #define GIM_INVALID_HASH 0xffffffff //!< A very very high value
- #define GIM_DEFAULT_HASH_TABLE_SIZE 380
- #define GIM_DEFAULT_HASH_TABLE_NODE_SIZE 4
- #define GIM_HASH_TABLE_GROW_FACTOR 2
- #define GIM_MIN_RADIX_SORT_SIZE 860 //!< calibrated on a PIII
- template<typename T>
- struct GIM_HASH_TABLE_NODE
- {
- GUINT m_key;
- T m_data;
- GIM_HASH_TABLE_NODE()
- {
- }
- GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE & value)
- {
- m_key = value.m_key;
- m_data = value.m_data;
- }
- GIM_HASH_TABLE_NODE(GUINT key, const T & data)
- {
- m_key = key;
- m_data = data;
- }
- bool operator <(const GIM_HASH_TABLE_NODE<T> & other) const
- {
- ///inverse order, further objects are first
- if(m_key < other.m_key) return true;
- return false;
- }
- bool operator >(const GIM_HASH_TABLE_NODE<T> & other) const
- {
- ///inverse order, further objects are first
- if(m_key > other.m_key) return true;
- return false;
- }
- bool operator ==(const GIM_HASH_TABLE_NODE<T> & other) const
- {
- ///inverse order, further objects are first
- if(m_key == other.m_key) return true;
- return false;
- }
- };
- ///Macro for getting the key
- class GIM_HASH_NODE_GET_KEY
- {
- public:
- template<class T>
- inline GUINT operator()( const T& a)
- {
- return a.m_key;
- }
- };
- ///Macro for comparing the key and the element
- class GIM_HASH_NODE_CMP_KEY_MACRO
- {
- public:
- template<class T>
- inline int operator() ( const T& a, GUINT key)
- {
- return ((int)(a.m_key - key));
- }
- };
- ///Macro for comparing Hash nodes
- class GIM_HASH_NODE_CMP_MACRO
- {
- public:
- template<class T>
- inline int operator() ( const T& a, const T& b )
- {
- return ((int)(a.m_key - b.m_key));
- }
- };
- //! Sorting for hash table
- /*!
- switch automatically between quicksort and radixsort
- */
- template<typename T>
- void gim_sort_hash_node_array(T * array, GUINT array_count)
- {
- if(array_count<GIM_MIN_RADIX_SORT_SIZE)
- {
- gim_heap_sort(array,array_count,GIM_HASH_NODE_CMP_MACRO());
- }
- else
- {
- memcopy_elements_func cmpfunc;
- gim_radix_sort(array,array_count,GIM_HASH_NODE_GET_KEY(),cmpfunc);
- }
- }
- // Note: assumes long is at least 32 bits.
- #define GIM_NUM_PRIME 28
- static const GUINT gim_prime_list[GIM_NUM_PRIME] =
- {
- 53ul, 97ul, 193ul, 389ul, 769ul,
- 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
- 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
- 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
- 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
- 1610612741ul, 3221225473ul, 4294967291ul
- };
- inline GUINT gim_next_prime(GUINT number)
- {
- //Find nearest upper prime
- GUINT result_ind = 0;
- gim_binary_search(gim_prime_list,0,(GIM_NUM_PRIME-2),number,result_ind);
- // inv: result_ind < 28
- return gim_prime_list[result_ind];
- }
- //! A compact hash table implementation
- /*!
- A memory aligned compact hash table that coud be treated as an array.
- It could be a simple sorted array without the overhead of the hash key bucked, or could
- be a formely hash table with an array of keys.
- You can use switch_to_hashtable() and switch_to_sorted_array for saving space or increase speed.
- </br>
- <ul>
- <li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
- When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
- <li> If node_size != 0, then this container becomes a hash table for ever
- </ul>
- */
- template<class T>
- class gim_hash_table
- {
- protected:
- typedef GIM_HASH_TABLE_NODE<T> _node_type;
- //!The nodes
- //array< _node_type, SuperAllocator<_node_type> > m_nodes;
- gim_array< _node_type > m_nodes;
- //SuperBufferedArray< _node_type > m_nodes;
- bool m_sorted;
- ///Hash table data management. The hash table has the indices to the corresponding m_nodes array
- GUINT * m_hash_table;//!<
- GUINT m_table_size;//!<
- GUINT m_node_size;//!<
- GUINT m_min_hash_table_size;
- //! Returns the cell index
- inline GUINT _find_cell(GUINT hashkey)
- {
- _node_type * nodesptr = m_nodes.pointer();
- GUINT start_index = (hashkey%m_table_size)*m_node_size;
- GUINT end_index = start_index + m_node_size;
- while(start_index<end_index)
- {
- GUINT value = m_hash_table[start_index];
- if(value != GIM_INVALID_HASH)
- {
- if(nodesptr[value].m_key == hashkey) return start_index;
- }
- start_index++;
- }
- return GIM_INVALID_HASH;
- }
- //! Find the avaliable cell for the hashkey, and return an existing cell if it has the same hash key
- inline GUINT _find_avaliable_cell(GUINT hashkey)
- {
- _node_type * nodesptr = m_nodes.pointer();
- GUINT avaliable_index = GIM_INVALID_HASH;
- GUINT start_index = (hashkey%m_table_size)*m_node_size;
- GUINT end_index = start_index + m_node_size;
- while(start_index<end_index)
- {
- GUINT value = m_hash_table[start_index];
- if(value == GIM_INVALID_HASH)
- {
- if(avaliable_index==GIM_INVALID_HASH)
- {
- avaliable_index = start_index;
- }
- }
- else if(nodesptr[value].m_key == hashkey)
- {
- return start_index;
- }
- start_index++;
- }
- return avaliable_index;
- }
- //! reserves the memory for the hash table.
- /*!
- \pre hash table must be empty
- \post reserves the memory for the hash table, an initializes all elements to GIM_INVALID_HASH.
- */
- inline void _reserve_table_memory(GUINT newtablesize)
- {
- if(newtablesize==0) return;
- if(m_node_size==0) return;
- //Get a Prime size
- m_table_size = gim_next_prime(newtablesize);
- GUINT datasize = m_table_size*m_node_size;
- //Alloc the data buffer
- m_hash_table = (GUINT *)gim_alloc(datasize*sizeof(GUINT));
- }
- inline void _invalidate_keys()
- {
- GUINT datasize = m_table_size*m_node_size;
- for(GUINT i=0;i<datasize;i++)
- {
- m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
- }
- }
- //! Clear all memory for the hash table
- inline void _clear_table_memory()
- {
- if(m_hash_table==NULL) return;
- gim_free(m_hash_table);
- m_hash_table = NULL;
- m_table_size = 0;
- }
- //! Invalidates the keys (Assigning GIM_INVALID_HASH to all) Reorders the hash keys
- inline void _rehash()
- {
- _invalidate_keys();
- _node_type * nodesptr = m_nodes.pointer();
- for(GUINT i=0;i<(GUINT)m_nodes.size();i++)
- {
- GUINT nodekey = nodesptr[i].m_key;
- if(nodekey != GIM_INVALID_HASH)
- {
- //Search for the avaliable cell in buffer
- GUINT index = _find_avaliable_cell(nodekey);
- if(m_hash_table[index]!=GIM_INVALID_HASH)
- {//The new index is alreade used... discard this new incomming object, repeated key
- btAssert(m_hash_table[index]==nodekey);
- nodesptr[i].m_key = GIM_INVALID_HASH;
- }
- else
- {
- //;
- //Assign the value for alloc
- m_hash_table[index] = i;
- }
- }
- }
- }
- //! Resize hash table indices
- inline void _resize_table(GUINT newsize)
- {
- //Clear memory
- _clear_table_memory();
- //Alloc the data
- _reserve_table_memory(newsize);
- //Invalidate keys and rehash
- _rehash();
- }
- //! Destroy hash table memory
- inline void _destroy()
- {
- if(m_hash_table==NULL) return;
- _clear_table_memory();
- }
- //! Finds an avaliable hash table cell, and resizes the table if there isn't space
- inline GUINT _assign_hash_table_cell(GUINT hashkey)
- {
- GUINT cell_index = _find_avaliable_cell(hashkey);
- if(cell_index==GIM_INVALID_HASH)
- {
- //rehashing
- _resize_table(m_table_size+1);
- GUINT cell_index = _find_avaliable_cell(hashkey);
- btAssert(cell_index!=GIM_INVALID_HASH);
- }
- return cell_index;
- }
- //! erase by index in hash table
- inline bool _erase_by_index_hash_table(GUINT index)
- {
- if(index >= m_nodes.size()) return false;
- if(m_nodes[index].m_key != GIM_INVALID_HASH)
- {
- //Search for the avaliable cell in buffer
- GUINT cell_index = _find_cell(m_nodes[index].m_key);
- btAssert(cell_index!=GIM_INVALID_HASH);
- btAssert(m_hash_table[cell_index]==index);
- m_hash_table[cell_index] = GIM_INVALID_HASH;
- }
- return this->_erase_unsorted(index);
- }
- //! erase by key in hash table
- inline bool _erase_hash_table(GUINT hashkey)
- {
- if(hashkey == GIM_INVALID_HASH) return false;
- //Search for the avaliable cell in buffer
- GUINT cell_index = _find_cell(hashkey);
- if(cell_index ==GIM_INVALID_HASH) return false;
- GUINT index = m_hash_table[cell_index];
- m_hash_table[cell_index] = GIM_INVALID_HASH;
- return this->_erase_unsorted(index);
- }
- //! insert an element in hash table
- /*!
- If the element exists, this won't insert the element
- \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
- If so, the element has been inserted at the last position of the array.
- */
- inline GUINT _insert_hash_table(GUINT hashkey, const T & value)
- {
- if(hashkey==GIM_INVALID_HASH)
- {
- //Insert anyway
- _insert_unsorted(hashkey,value);
- return GIM_INVALID_HASH;
- }
- GUINT cell_index = _assign_hash_table_cell(hashkey);
- GUINT value_key = m_hash_table[cell_index];
- if(value_key!= GIM_INVALID_HASH) return value_key;// Not overrited
- m_hash_table[cell_index] = m_nodes.size();
- _insert_unsorted(hashkey,value);
- return GIM_INVALID_HASH;
- }
- //! insert an element in hash table.
- /*!
- If the element exists, this replaces the element.
- \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
- If so, the element has been inserted at the last position of the array.
- */
- inline GUINT _insert_hash_table_replace(GUINT hashkey, const T & value)
- {
- if(hashkey==GIM_INVALID_HASH)
- {
- //Insert anyway
- _insert_unsorted(hashkey,value);
- return GIM_INVALID_HASH;
- }
- GUINT cell_index = _assign_hash_table_cell(hashkey);
- GUINT value_key = m_hash_table[cell_index];
- if(value_key!= GIM_INVALID_HASH)
- {//replaces the existing
- m_nodes[value_key] = _node_type(hashkey,value);
- return value_key;// index of the replaced element
- }
- m_hash_table[cell_index] = m_nodes.size();
- _insert_unsorted(hashkey,value);
- return GIM_INVALID_HASH;
- }
-
- ///Sorted array data management. The hash table has the indices to the corresponding m_nodes array
- inline bool _erase_sorted(GUINT index)
- {
- if(index>=(GUINT)m_nodes.size()) return false;
- m_nodes.erase_sorted(index);
- if(m_nodes.size()<2) m_sorted = false;
- return true;
- }
- //! faster, but unsorted
- inline bool _erase_unsorted(GUINT index)
- {
- if(index>=m_nodes.size()) return false;
- GUINT lastindex = m_nodes.size()-1;
- if(index<lastindex && m_hash_table!=0)
- {
- GUINT hashkey = m_nodes[lastindex].m_key;
- if(hashkey!=GIM_INVALID_HASH)
- {
- //update the new position of the last element
- GUINT cell_index = _find_cell(hashkey);
- btAssert(cell_index!=GIM_INVALID_HASH);
- //new position of the last element which will be swaped
- m_hash_table[cell_index] = index;
- }
- }
- m_nodes.erase(index);
- m_sorted = false;
- return true;
- }
- //! Insert in position ordered
- /*!
- Also checks if it is needed to transform this container to a hash table, by calling check_for_switching_to_hashtable
- */
- inline void _insert_in_pos(GUINT hashkey, const T & value, GUINT pos)
- {
- m_nodes.insert(_node_type(hashkey,value),pos);
- this->check_for_switching_to_hashtable();
- }
- //! Insert an element in an ordered array
- inline GUINT _insert_sorted(GUINT hashkey, const T & value)
- {
- if(hashkey==GIM_INVALID_HASH || size()==0)
- {
- m_nodes.push_back(_node_type(hashkey,value));
- return GIM_INVALID_HASH;
- }
- //Insert at last position
- //Sort element
- GUINT result_ind=0;
- GUINT last_index = m_nodes.size()-1;
- _node_type * ptr = m_nodes.pointer();
- bool found = gim_binary_search_ex(
- ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
- //Insert before found index
- if(found)
- {
- return result_ind;
- }
- else
- {
- _insert_in_pos(hashkey, value, result_ind);
- }
- return GIM_INVALID_HASH;
- }
- inline GUINT _insert_sorted_replace(GUINT hashkey, const T & value)
- {
- if(hashkey==GIM_INVALID_HASH || size()==0)
- {
- m_nodes.push_back(_node_type(hashkey,value));
- return GIM_INVALID_HASH;
- }
- //Insert at last position
- //Sort element
- GUINT result_ind;
- GUINT last_index = m_nodes.size()-1;
- _node_type * ptr = m_nodes.pointer();
- bool found = gim_binary_search_ex(
- ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
- //Insert before found index
- if(found)
- {
- m_nodes[result_ind] = _node_type(hashkey,value);
- }
- else
- {
- _insert_in_pos(hashkey, value, result_ind);
- }
- return result_ind;
- }
- //! Fast insertion in m_nodes array
- inline GUINT _insert_unsorted(GUINT hashkey, const T & value)
- {
- m_nodes.push_back(_node_type(hashkey,value));
- m_sorted = false;
- return GIM_INVALID_HASH;
- }
-
- public:
- /*!
- <li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
- When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
- <li> If node_size != 0, then this container becomes a hash table for ever
- </ul>
- */
- gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE,
- GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE,
- GUINT min_hash_table_size = GIM_INVALID_HASH)
- {
- m_hash_table = NULL;
- m_table_size = 0;
- m_sorted = false;
- m_node_size = node_size;
- m_min_hash_table_size = min_hash_table_size;
- if(m_node_size!=0)
- {
- if(reserve_size!=0)
- {
- m_nodes.reserve(reserve_size);
- _reserve_table_memory(reserve_size);
- _invalidate_keys();
- }
- else
- {
- m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE);
- _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE);
- _invalidate_keys();
- }
- }
- else if(reserve_size!=0)
- {
- m_nodes.reserve(reserve_size);
- }
- }
- ~gim_hash_table()
- {
- _destroy();
- }
- inline bool is_hash_table()
- {
- if(m_hash_table) return true;
- return false;
- }
- inline bool is_sorted()
- {
- if(size()<2) return true;
- return m_sorted;
- }
- bool sort()
- {
- if(is_sorted()) return true;
- if(m_nodes.size()<2) return false;
- _node_type * ptr = m_nodes.pointer();
- GUINT siz = m_nodes.size();
- gim_sort_hash_node_array(ptr,siz);
- m_sorted=true;
- if(m_hash_table)
- {
- _rehash();
- }
- return true;
- }
- bool switch_to_hashtable()
- {
- if(m_hash_table) return false;
- if(m_node_size==0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
- if(m_nodes.size()<GIM_DEFAULT_HASH_TABLE_SIZE)
- {
- _resize_table(GIM_DEFAULT_HASH_TABLE_SIZE);
- }
- else
- {
- _resize_table(m_nodes.size()+1);
- }
- return true;
- }
- bool switch_to_sorted_array()
- {
- if(m_hash_table==NULL) return true;
- _clear_table_memory();
- return sort();
- }
- //!If the container reaches the
- bool check_for_switching_to_hashtable()
- {
- if(this->m_hash_table) return true;
- if(!(m_nodes.size()< m_min_hash_table_size))
- {
- if(m_node_size == 0)
- {
- m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
- }
- _resize_table(m_nodes.size()+1);
- return true;
- }
- return false;
- }
- inline void set_sorted(bool value)
- {
- m_sorted = value;
- }
- //! Retrieves the amount of keys.
- inline GUINT size() const
- {
- return m_nodes.size();
- }
- //! Retrieves the hash key.
- inline GUINT get_key(GUINT index) const
- {
- return m_nodes[index].m_key;
- }
- //! Retrieves the value by index
- /*!
- */
- inline T * get_value_by_index(GUINT index)
- {
- return &m_nodes[index].m_data;
- }
- inline const T& operator[](GUINT index) const
- {
- return m_nodes[index].m_data;
- }
- inline T& operator[](GUINT index)
- {
- return m_nodes[index].m_data;
- }
- //! Finds the index of the element with the key
- /*!
- \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
- If so, the element has been inserted at the last position of the array.
- */
- inline GUINT find(GUINT hashkey)
- {
- if(m_hash_table)
- {
- GUINT cell_index = _find_cell(hashkey);
- if(cell_index==GIM_INVALID_HASH) return GIM_INVALID_HASH;
- return m_hash_table[cell_index];
- }
- GUINT last_index = m_nodes.size();
- if(last_index<2)
- {
- if(last_index==0) return GIM_INVALID_HASH;
- if(m_nodes[0].m_key == hashkey) return 0;
- return GIM_INVALID_HASH;
- }
- else if(m_sorted)
- {
- //Binary search
- GUINT result_ind = 0;
- last_index--;
- _node_type * ptr = m_nodes.pointer();
- bool found = gim_binary_search_ex(ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
- if(found) return result_ind;
- }
- return GIM_INVALID_HASH;
- }
- //! Retrieves the value associated with the index
- /*!
- \return the found element, or null
- */
- inline T * get_value(GUINT hashkey)
- {
- GUINT index = find(hashkey);
- if(index == GIM_INVALID_HASH) return NULL;
- return &m_nodes[index].m_data;
- }
- /*!
- */
- inline bool erase_by_index(GUINT index)
- {
- if(index > m_nodes.size()) return false;
- if(m_hash_table == NULL)
- {
- if(is_sorted())
- {
- return this->_erase_sorted(index);
- }
- else
- {
- return this->_erase_unsorted(index);
- }
- }
- else
- {
- return this->_erase_by_index_hash_table(index);
- }
- return false;
- }
- inline bool erase_by_index_unsorted(GUINT index)
- {
- if(index > m_nodes.size()) return false;
- if(m_hash_table == NULL)
- {
- return this->_erase_unsorted(index);
- }
- else
- {
- return this->_erase_by_index_hash_table(index);
- }
- return false;
- }
- /*!
- */
- inline bool erase_by_key(GUINT hashkey)
- {
- if(size()==0) return false;
- if(m_hash_table)
- {
- return this->_erase_hash_table(hashkey);
- }
- //Binary search
- if(is_sorted()==false) return false;
- GUINT result_ind = find(hashkey);
- if(result_ind!= GIM_INVALID_HASH)
- {
- return this->_erase_sorted(result_ind);
- }
- return false;
- }
- void clear()
- {
- m_nodes.clear();
- if(m_hash_table==NULL) return;
- GUINT datasize = m_table_size*m_node_size;
- //Initialize the hashkeys.
- GUINT i;
- for(i=0;i<datasize;i++)
- {
- m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
- }
- m_sorted = false;
- }
- //! Insert an element into the hash
- /*!
- \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
- of the existing element.
- */
- inline GUINT insert(GUINT hashkey, const T & element)
- {
- if(m_hash_table)
- {
- return this->_insert_hash_table(hashkey,element);
- }
- if(this->is_sorted())
- {
- return this->_insert_sorted(hashkey,element);
- }
- return this->_insert_unsorted(hashkey,element);
- }
- //! Insert an element into the hash, and could overrite an existing object with the same hash.
- /*!
- \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
- of the replaced element.
- */
- inline GUINT insert_override(GUINT hashkey, const T & element)
- {
- if(m_hash_table)
- {
- return this->_insert_hash_table_replace(hashkey,element);
- }
- if(this->is_sorted())
- {
- return this->_insert_sorted_replace(hashkey,element);
- }
- this->_insert_unsorted(hashkey,element);
- return m_nodes.size();
- }
- //! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted
- /*!
- */
- inline GUINT insert_unsorted(GUINT hashkey,const T & element)
- {
- if(m_hash_table)
- {
- return this->_insert_hash_table(hashkey,element);
- }
- return this->_insert_unsorted(hashkey,element);
- }
- };
- #endif // GIM_CONTAINERS_H_INCLUDED
|