HashSet.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #pragma once
  24. #include "HashBase.h"
  25. /// Hash-based set template class
  26. template <class T> class HashSet : public HashBase
  27. {
  28. public:
  29. /// Hash set node
  30. struct Node : public HashNodeBase
  31. {
  32. // Construct undefined
  33. Node()
  34. {
  35. }
  36. /// Construct with key
  37. Node(const T& key) :
  38. key_(key)
  39. {
  40. }
  41. /// Key
  42. T key_;
  43. /// Return next node
  44. Node* Next() const { return static_cast<Node*>(next_); }
  45. /// Return previous node
  46. Node* Prev() const { return static_cast<Node*>(prev_); }
  47. /// Return next node in the bucket
  48. Node* Down() const { return static_cast<Node*>(down_); }
  49. };
  50. /// Hash set node iterator
  51. class Iterator : public HashIteratorBase
  52. {
  53. public:
  54. /// Construct
  55. Iterator(Node* ptr) :
  56. HashIteratorBase(ptr)
  57. {
  58. }
  59. /// Preincrement the pointer
  60. Iterator& operator ++ () { GotoNext(); return *this; }
  61. /// Postincrement the pointer
  62. Iterator operator ++ (int) { Iterator it = *this; GotoNext(); return it; }
  63. /// Predecrement the pointer
  64. Iterator& operator -- () { GotoPrev(); return *this; }
  65. /// Postdecrement the pointer
  66. Iterator operator -- (int) { Iterator it = *this; GotoPrev(); return it; }
  67. /// Point to the key
  68. const T* operator -> () const { return &(static_cast<Node*>(ptr_))->key_; }
  69. /// Dereference the key
  70. const T& operator * () const { return (static_cast<Node*>(ptr_))->key_; }
  71. };
  72. /// Hash set node const iterator
  73. class ConstIterator : public HashIteratorBase
  74. {
  75. public:
  76. /// Construct
  77. ConstIterator(Node* ptr) :
  78. HashIteratorBase(ptr)
  79. {
  80. }
  81. /// Construct from a non-const iterator
  82. ConstIterator(const Iterator& rhs) :
  83. HashIteratorBase(rhs.ptr_)
  84. {
  85. }
  86. /// Assign from a non-const iterator
  87. ConstIterator& operator = (const Iterator& rhs) { ptr_ = rhs.ptr_; return *this; }
  88. /// Preincrement the pointer
  89. Iterator& operator ++ () { GotoNext(); return *this; }
  90. /// Postincrement the pointer
  91. Iterator operator ++ (int) { Iterator it = *this; GotoNext(); return it; }
  92. /// Predecrement the pointer
  93. Iterator& operator -- () { GotoPrev(); return *this; }
  94. /// Postdecrement the pointer
  95. Iterator operator -- (int) { Iterator it = *this; GotoPrev(); return it; }
  96. /// Point to the key
  97. const T* operator -> () const { return &(static_cast<Node*>(ptr_))->key_; }
  98. /// Dereference the key
  99. const T& operator * () const { return (static_cast<Node*>(ptr_))->key_; }
  100. };
  101. /// Construct empty
  102. HashSet()
  103. {
  104. // Reserve the tail node
  105. allocator_ = AllocatorInitialize(sizeof(Node));
  106. head_ = tail_ = ReserveNode();
  107. }
  108. /// Construct from another hash set
  109. HashSet(const HashSet<T>& set)
  110. {
  111. // Reserve the tail node
  112. allocator_ = AllocatorInitialize(sizeof(Node));
  113. head_ = tail_ = ReserveNode();
  114. *this = set;
  115. }
  116. /// Destruct
  117. ~HashSet()
  118. {
  119. Clear();
  120. FreeNode(Tail());
  121. AllocatorUninitialize(allocator_);
  122. delete[] ptrs_;
  123. }
  124. /// Assign a hash set
  125. HashSet& operator = (const HashSet<T>& rhs)
  126. {
  127. Clear();
  128. Insert(rhs.Begin(), rhs.End());
  129. return *this;
  130. }
  131. /// Add-assign a value
  132. HashSet& operator += (const T& rhs)
  133. {
  134. Insert(rhs);
  135. return *this;
  136. }
  137. /// Add-assign a hash set
  138. HashSet& operator += (const HashSet<T>& rhs)
  139. {
  140. Insert(rhs.Begin(), rhs.End());
  141. return *this;
  142. }
  143. /// Insert a key. Return an iterator to it
  144. Iterator Insert(const T& key)
  145. {
  146. // If no pointers yet, allocate with minimum bucket count
  147. if (!ptrs_)
  148. {
  149. numBuckets_ = MIN_BUCKETS;
  150. Rehash();
  151. }
  152. unsigned hashKey = MakeHash(key) & (numBuckets_ - 1);
  153. Node* existing = FindNode(key, hashKey);
  154. if (existing)
  155. return Iterator(existing);
  156. Node** ptrs = Ptrs();
  157. Node* newNode = InsertNode(Tail(), key);
  158. newNode->down_ = ptrs[hashKey];
  159. ptrs[hashKey] = newNode;
  160. // Rehash if the maximum load factor has been exceeded
  161. if (size_ > numBuckets_ * MAX_LOAD_FACTOR)
  162. {
  163. numBuckets_ <<= 1;
  164. Rehash();
  165. }
  166. return Iterator(newNode);
  167. }
  168. /// Insert a set
  169. void Insert(const HashSet<T>& set)
  170. {
  171. Insert(set.Begin(), set.End());
  172. }
  173. /// Insert a key by iterator. Return iterator to the value
  174. Iterator Insert(const ConstIterator& it)
  175. {
  176. return Iterator(InsertNode(*it));
  177. }
  178. /// Insert a range by iterators
  179. void Insert(const ConstIterator& start, const ConstIterator& end)
  180. {
  181. ConstIterator it = start;
  182. while (it != end)
  183. InsertNode(*it++);
  184. }
  185. /// Erase a key. Return true if was found
  186. bool Erase(const T& key)
  187. {
  188. if (!numBuckets_)
  189. return false;
  190. unsigned hashKey = MakeHash(key) & (numBuckets_ - 1);
  191. Node* previous;
  192. Node* node = FindNode(key, hashKey, previous);
  193. if (!node)
  194. return false;
  195. if (previous)
  196. previous->next_ = node->next_;
  197. else
  198. ptrs_[hashKey] = node->next_;
  199. EraseNode(node);
  200. return true;
  201. }
  202. /// Erase a key by iterator
  203. void Erase(const Iterator& it)
  204. {
  205. return Erase(*it);
  206. }
  207. /// Erase a range by iterators
  208. void Erase(const Iterator& start, const Iterator& end)
  209. {
  210. Iterator it = start;
  211. while (it != end)
  212. {
  213. Iterator current = it++;
  214. Erase(current);
  215. }
  216. }
  217. /// Clear the set
  218. void Clear()
  219. {
  220. while (size_)
  221. EraseNode(Head());
  222. // Reset bucket pointers
  223. for (unsigned i = 0; i < numBuckets_; ++i)
  224. ptrs_[i] = 0;
  225. }
  226. /// Return iterator to the key, or end iterator if not found
  227. Iterator Find(const T& key)
  228. {
  229. if (!numBuckets_)
  230. return End();
  231. unsigned hashKey = MakeHash(key) & (numBuckets_ - 1);
  232. Node* node = FindNode(key, hashKey);
  233. if (node)
  234. return Iterator(node);
  235. else
  236. return End();
  237. }
  238. /// Return const iterator to the key, or end iterator if not found
  239. ConstIterator Find(const T& key) const
  240. {
  241. if (!numBuckets_)
  242. return End();
  243. unsigned hashKey = MakeHash(key) & (numBuckets_ - 1);
  244. Node* node = FindNode(key, hashKey);
  245. if (node)
  246. return ConstIterator(node);
  247. else
  248. return End();
  249. }
  250. /// Return whether contains a key
  251. bool Contains(const T& key) const
  252. {
  253. if (!numBuckets_)
  254. return false;
  255. unsigned hashKey = MakeHash(key) & (numBuckets_ - 1);
  256. return FindNode(key, hashKey) != 0;
  257. }
  258. /// Return iterator to the beginning
  259. Iterator Begin() { return Iterator(Head()); }
  260. /// Return iterator to the beginning
  261. ConstIterator Begin() const { return ConstIterator(Head()); }
  262. /// Return iterator to the end
  263. Iterator End() { return Iterator(Tail()); }
  264. /// Return iterator to the end
  265. ConstIterator End() const { return ConstIterator(Tail()); }
  266. /// Return first key
  267. const T& Front() const { return *Begin(); }
  268. /// Return last key
  269. const T& Back() const { return *(--End()); }
  270. /// Return number of keys
  271. unsigned Size() const { return size_; }
  272. /// Return whether set is empty
  273. bool Empty() const { return size_ == 0; }
  274. private:
  275. /// Return the head pointer with correct type
  276. Node* Head() const { return reinterpret_cast<Node*>(head_); }
  277. /// Return the tail pointer with correct type
  278. Node* Tail() const { return reinterpret_cast<Node*>(tail_); }
  279. /// Return the bucket pointers with correct type
  280. Node** Ptrs() const { return reinterpret_cast<Node**>(ptrs_); }
  281. /// Find a node from the buckets
  282. Node* FindNode(const T& key, unsigned hashKey) const
  283. {
  284. Node** ptrs = Ptrs();
  285. if (!ptrs)
  286. return 0;
  287. Node* node = ptrs[hashKey];
  288. while (node)
  289. {
  290. if (node->key_ == key)
  291. return node;
  292. node = node->Down();
  293. }
  294. return 0;
  295. }
  296. /// Find a node and the previous node from the buckets
  297. Node* FindNode(const T& key, unsigned hashKey, Node*& previous) const
  298. {
  299. previous = 0;
  300. Node** ptrs = Ptrs();
  301. if (!ptrs)
  302. return 0;
  303. Node* node = ptrs[hashKey];
  304. while (node)
  305. {
  306. if (node->key_ == key)
  307. return node;
  308. previous = node;
  309. node = node->Down();
  310. }
  311. return 0;
  312. }
  313. /// Insert a node into the list. Return the new node
  314. Node* InsertNode(Node* dest, const T& key)
  315. {
  316. if (!dest)
  317. return 0;
  318. Node* newNode = ReserveNode(key);
  319. Node* prev = dest->Prev();
  320. newNode->next_ = dest;
  321. newNode->prev_ = prev;
  322. if (prev)
  323. prev->next_ = newNode;
  324. dest->prev_ = newNode;
  325. // Reassign the head node if necessary
  326. if (dest == Head())
  327. head_ = newNode;
  328. ++size_;
  329. return newNode;
  330. }
  331. /// Erase a node from the list. Return pointer to the next element, or to the end if could not erase
  332. Node* EraseNode(Node* toRemove)
  333. {
  334. // The tail node can not be removed
  335. if ((!toRemove) || (toRemove == tail_))
  336. return Tail();
  337. Node* prev = toRemove->Prev();
  338. Node* next = toRemove->Next();
  339. if (prev)
  340. prev->next_ = next;
  341. next->prev_ = prev;
  342. // Reassign the head node if necessary
  343. if (toRemove == Head())
  344. head_ = next;
  345. FreeNode(toRemove);
  346. --size_;
  347. return next;
  348. }
  349. /// Reserve a node
  350. Node* ReserveNode()
  351. {
  352. Node* newNode = static_cast<Node*>(AllocatorReserve(allocator_));
  353. new(newNode) Node();
  354. return newNode;
  355. }
  356. /// Reserve a node with specified key
  357. Node* ReserveNode(const T& key)
  358. {
  359. if (!allocator_)
  360. allocator_ = AllocatorInitialize(sizeof(Node));
  361. Node* newNode = static_cast<Node*>(AllocatorReserve(allocator_));
  362. new(newNode) Node(key);
  363. return newNode;
  364. }
  365. /// Free a node
  366. void FreeNode(Node* node)
  367. {
  368. (node)->~Node();
  369. AllocatorFree(allocator_, node);
  370. }
  371. /// Reallocate and rehash the buckets
  372. void Rehash()
  373. {
  374. delete[] ptrs_;
  375. ptrs_ = new HashNodeBase*[numBuckets_];
  376. for (unsigned i = 0; i < numBuckets_; ++i)
  377. ptrs_[i] = 0;
  378. for (Iterator i = Begin(); i != End(); ++i)
  379. {
  380. Node* node = reinterpret_cast<Node*>(i.ptr_);
  381. unsigned hashKey = MakeHash(*i) & (numBuckets_ - 1);
  382. node->down_ = ptrs_[hashKey];
  383. ptrs_[hashKey] = node;
  384. }
  385. }
  386. };