HashSet.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  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. ConstIterator& operator ++ () { GotoNext(); return *this; }
  90. /// Postincrement the pointer
  91. ConstIterator operator ++ (int) { ConstIterator it = *this; GotoNext(); return it; }
  92. /// Predecrement the pointer
  93. ConstIterator& operator -- () { GotoPrev(); return *this; }
  94. /// Postdecrement the pointer
  95. ConstIterator operator -- (int) { ConstIterator 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);
  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);
  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. ConstIterator it = set.Begin();
  172. ConstIterator end = set.End();
  173. while (it != end)
  174. Insert(*it++);
  175. }
  176. /// Insert a key by iterator. Return iterator to the value
  177. Iterator Insert(const ConstIterator& it)
  178. {
  179. return Iterator(InsertNode(*it));
  180. }
  181. /// Erase a key. Return true if was found
  182. bool Erase(const T& key)
  183. {
  184. if (!numBuckets_)
  185. return false;
  186. unsigned hashKey = MakeHash(key) & (numBuckets_ - 1);
  187. Node* previous;
  188. Node* node = FindNode(key, hashKey, previous);
  189. if (!node)
  190. return false;
  191. if (previous)
  192. previous->down_ = node->down_;
  193. else
  194. ptrs_[hashKey] = node->down_;
  195. EraseNode(node);
  196. return true;
  197. }
  198. /// Erase a key by iterator
  199. void Erase(const Iterator& it)
  200. {
  201. Erase(*it);
  202. }
  203. /// Clear the set
  204. void Clear()
  205. {
  206. while (size_)
  207. EraseNode(Head());
  208. // Reset bucket pointers
  209. for (unsigned i = 0; i < numBuckets_; ++i)
  210. ptrs_[i] = 0;
  211. }
  212. /// Return iterator to the key, or end iterator if not found
  213. Iterator Find(const T& key)
  214. {
  215. if (!numBuckets_)
  216. return End();
  217. unsigned hashKey = MakeHash(key) & (numBuckets_ - 1);
  218. Node* node = FindNode(key, hashKey);
  219. if (node)
  220. return Iterator(node);
  221. else
  222. return End();
  223. }
  224. /// Return const iterator to the key, or end iterator if not found
  225. ConstIterator Find(const T& key) const
  226. {
  227. if (!numBuckets_)
  228. return End();
  229. unsigned hashKey = MakeHash(key) & (numBuckets_ - 1);
  230. Node* node = FindNode(key, hashKey);
  231. if (node)
  232. return ConstIterator(node);
  233. else
  234. return End();
  235. }
  236. /// Return whether contains a key
  237. bool Contains(const T& key) const
  238. {
  239. if (!numBuckets_)
  240. return false;
  241. unsigned hashKey = MakeHash(key) & (numBuckets_ - 1);
  242. return FindNode(key, hashKey) != 0;
  243. }
  244. /// Return iterator to the beginning
  245. Iterator Begin() { return Iterator(Head()); }
  246. /// Return iterator to the beginning
  247. ConstIterator Begin() const { return ConstIterator(Head()); }
  248. /// Return iterator to the end
  249. Iterator End() { return Iterator(Tail()); }
  250. /// Return iterator to the end
  251. ConstIterator End() const { return ConstIterator(Tail()); }
  252. /// Return first key
  253. const T& Front() const { return *Begin(); }
  254. /// Return last key
  255. const T& Back() const { return *(--End()); }
  256. /// Return number of keys
  257. unsigned Size() const { return size_; }
  258. /// Return whether set is empty
  259. bool Empty() const { return size_ == 0; }
  260. private:
  261. /// Return the head pointer with correct type
  262. Node* Head() const { return reinterpret_cast<Node*>(head_); }
  263. /// Return the tail pointer with correct type
  264. Node* Tail() const { return reinterpret_cast<Node*>(tail_); }
  265. /// Return the bucket pointers with correct type
  266. Node** Ptrs() const { return reinterpret_cast<Node**>(ptrs_); }
  267. /// Find a node from the buckets
  268. Node* FindNode(const T& key, unsigned hashKey) const
  269. {
  270. Node** ptrs = Ptrs();
  271. if (!ptrs)
  272. return 0;
  273. Node* node = ptrs[hashKey];
  274. while (node)
  275. {
  276. if (node->key_ == key)
  277. return node;
  278. node = node->Down();
  279. }
  280. return 0;
  281. }
  282. /// Find a node and the previous node from the buckets
  283. Node* FindNode(const T& key, unsigned hashKey, Node*& previous) const
  284. {
  285. previous = 0;
  286. Node** ptrs = Ptrs();
  287. if (!ptrs)
  288. return 0;
  289. Node* node = ptrs[hashKey];
  290. while (node)
  291. {
  292. if (node->key_ == key)
  293. return node;
  294. previous = node;
  295. node = node->Down();
  296. }
  297. return 0;
  298. }
  299. /// Insert a node into the list. Return the new node
  300. Node* InsertNode(Node* dest, const T& key)
  301. {
  302. if (!dest)
  303. return 0;
  304. Node* newNode = ReserveNode(key);
  305. Node* prev = dest->Prev();
  306. newNode->next_ = dest;
  307. newNode->prev_ = prev;
  308. if (prev)
  309. prev->next_ = newNode;
  310. dest->prev_ = newNode;
  311. // Reassign the head node if necessary
  312. if (dest == Head())
  313. head_ = newNode;
  314. ++size_;
  315. return newNode;
  316. }
  317. /// Erase a node from the list. Return pointer to the next element, or to the end if could not erase
  318. Node* EraseNode(Node* toRemove)
  319. {
  320. // The tail node can not be removed
  321. if (!toRemove || toRemove == tail_)
  322. return Tail();
  323. Node* prev = toRemove->Prev();
  324. Node* next = toRemove->Next();
  325. if (prev)
  326. prev->next_ = next;
  327. next->prev_ = prev;
  328. // Reassign the head node if necessary
  329. if (toRemove == Head())
  330. head_ = next;
  331. FreeNode(toRemove);
  332. --size_;
  333. return next;
  334. }
  335. /// Reserve a node
  336. Node* ReserveNode()
  337. {
  338. Node* newNode = static_cast<Node*>(AllocatorReserve(allocator_));
  339. new(newNode) Node();
  340. return newNode;
  341. }
  342. /// Reserve a node with specified key
  343. Node* ReserveNode(const T& key)
  344. {
  345. if (!allocator_)
  346. allocator_ = AllocatorInitialize(sizeof(Node));
  347. Node* newNode = static_cast<Node*>(AllocatorReserve(allocator_));
  348. new(newNode) Node(key);
  349. return newNode;
  350. }
  351. /// Free a node
  352. void FreeNode(Node* node)
  353. {
  354. (node)->~Node();
  355. AllocatorFree(allocator_, node);
  356. }
  357. /// Reallocate and rehash the buckets
  358. void Rehash()
  359. {
  360. delete[] ptrs_;
  361. ptrs_ = new HashNodeBase*[numBuckets_];
  362. for (unsigned i = 0; i < numBuckets_; ++i)
  363. ptrs_[i] = 0;
  364. for (Iterator i = Begin(); i != End(); ++i)
  365. {
  366. Node* node = reinterpret_cast<Node*>(i.ptr_);
  367. unsigned hashKey = MakeHash(*i) & (numBuckets_ - 1);
  368. node->down_ = ptrs_[hashKey];
  369. ptrs_[hashKey] = node;
  370. }
  371. }
  372. };