sve_vash

Untitled

Nov 28th, 2019
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.63 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <cmath>
  4. #include <functional>
  5. #include <memory>
  6. #include <utility>
  7. #include <type_traits>
  8. #include <vector>
  9. #include <limits>
  10.  
  11. namespace fefu
  12. {
  13.  
  14. template<typename T>
  15. //класс, выделяющий и управляющий памятью
  16. class allocator {
  17. public:
  18. using size_type = std::size_t;
  19. using difference_type = std::ptrdiff_t;
  20. using pointer = T*;
  21. using const_pointer = const T*;
  22. using reference = typename std::add_lvalue_reference<T>::type;
  23. using const_reference = typename std::add_lvalue_reference<const T>::type;
  24. using value_type = T;
  25.  
  26. allocator() noexcept : x(10) {};
  27.  
  28. explicit allocator(int k): x(k){}
  29.  
  30. allocator(const allocator& k) noexcept : x(k.x) {}
  31.  
  32. template <class U>
  33. allocator(const allocator<U>& k) noexcept : x(k.x) {};
  34.  
  35. ~allocator() = default;
  36.  
  37. pointer allocate(size_type n) {
  38. auto p = ::operator new(n * sizeof(value_type));
  39. return static_cast<pointer>(p);
  40. }
  41.  
  42. void deallocate(pointer p, size_type n) noexcept {
  43. if (p != nullptr) {
  44. ::operator delete(p, n * sizeof(value_type));
  45. }
  46. }
  47.  
  48. int x;
  49. };
  50.  
  51. template<typename ValueType>
  52. class hash_map_const_iterator;
  53.  
  54. template<typename ValueType>
  55. class hash_map_iterator {
  56. public:
  57.  
  58. template<typename, typename, typename, typename, typename>
  59. friend class hash_map;
  60.  
  61. template<typename>
  62. friend class hash_map_const_iterator;
  63.  
  64. using iterator_category = std::forward_iterator_tag;
  65. using value_type = ValueType;
  66. using difference_type = std::ptrdiff_t;
  67. using reference = ValueType&;
  68. using pointer = ValueType*;
  69.  
  70. hash_map_iterator() noexcept = default;
  71. hash_map_iterator(const hash_map_iterator& other) noexcept : start(other.start),
  72. state(other.state), position(other.position) {}
  73.  
  74. reference operator*() const {
  75. return *(start + position);
  76. }
  77.  
  78. pointer operator->() const {
  79. return start + position;
  80. }
  81.  
  82. // prefix ++
  83. hash_map_iterator& operator++() {
  84. while (true) {
  85. position++;
  86.  
  87. if (position == state->size()) {
  88. break;
  89. }
  90.  
  91.  
  92. if(*(state->data() + position) == 1) {
  93. break;
  94. }
  95. }
  96.  
  97. return *this;
  98. }
  99.  
  100. // postfix ++
  101. hash_map_iterator operator++(int) {
  102. hash_map_iterator tmp = *this;
  103.  
  104. while (true) {
  105. position++;
  106.  
  107. if ((position) == state->size()) {
  108. break;
  109. }
  110.  
  111. if(*(state->data() + position) == 1) {
  112. break;
  113. }
  114. }
  115.  
  116. return tmp;
  117. }
  118.  
  119. friend bool operator==(const hash_map_iterator<ValueType>& a, const hash_map_iterator<ValueType>& b) {
  120. if (a.state == b.state) {
  121. if (a.start == b.start) {
  122. if (a.position == b.position) {
  123. return true;
  124. }
  125. }
  126. }
  127. return false;
  128. }
  129.  
  130. friend bool operator!=(const hash_map_iterator<ValueType>& a, const hash_map_iterator<ValueType>& b) {
  131. return !(a == b);
  132. }
  133.  
  134. private:
  135. const pointer start;
  136. const std::vector<char>* state;
  137. size_t position;
  138. hash_map_iterator(pointer p, std::vector<char> *st, size_t pos): start(p), state(st), position(pos) {}
  139. hash_map_iterator(const hash_map_const_iterator<ValueType>& other) noexcept :
  140. start(const_cast<pointer>(other.start)),
  141. state(const_cast<std::vector<char>*>(other.state)),
  142. position(other.position) {}
  143. };
  144.  
  145. template<typename ValueType>
  146. class hash_map_const_iterator {
  147. // Shouldn't give non const references on value
  148. public:
  149. template<typename, typename, typename, typename, typename>
  150. friend class hash_map;
  151.  
  152. template<typename>
  153. friend class hash_map_iterator;
  154.  
  155. using iterator_category = std::forward_iterator_tag;
  156. using value_type = ValueType;
  157. using difference_type = std::ptrdiff_t;
  158. using reference = const ValueType&;
  159. using pointer = const ValueType*;
  160.  
  161. hash_map_const_iterator() noexcept = default;
  162. hash_map_const_iterator(const hash_map_const_iterator& other) noexcept : start(other.start), state(other.state),
  163. position(other.position) {}
  164. hash_map_const_iterator(const hash_map_iterator<ValueType>& other) noexcept : start(other.start), state(other.state),
  165. position(other.position) {}
  166.  
  167. reference operator*() const {
  168. return *(start + position);
  169. }
  170.  
  171. pointer operator->() const {
  172. return start + position;
  173. }
  174.  
  175. // prefix ++
  176. hash_map_const_iterator& operator++() {
  177. while (true) {
  178. position++;
  179.  
  180. if ((position) == state->size()) {
  181. break;
  182. }
  183.  
  184. if(*(state->data() + position) == 1) {
  185. break;
  186. }
  187. }
  188. return *this;
  189. }
  190.  
  191. // postfix ++
  192. hash_map_const_iterator operator++(int) {
  193. hash_map_const_iterator tmp = *this;
  194.  
  195. while (true) {
  196. position++;
  197.  
  198. if ((position) == state->size()) {
  199. break;
  200. }
  201.  
  202. if(*(state->data() + position) == 1) {
  203. break;
  204. }
  205. }
  206. return tmp;
  207. }
  208.  
  209. friend bool operator==(const hash_map_const_iterator<ValueType>& a, const hash_map_const_iterator<ValueType>& b){
  210. if (a.state == b.state) {
  211. if (a.start == b.start) {
  212. if (a.position == b.position) {
  213. return true;
  214. }
  215. }
  216. }
  217. return false;
  218. }
  219. friend bool operator!=(const hash_map_const_iterator<ValueType>& a, const hash_map_const_iterator<ValueType>& b) {
  220. return !(a == b);
  221. }
  222.  
  223. private:
  224. pointer start;
  225. const std::vector<char>* state;
  226. size_t position;
  227. hash_map_const_iterator(const pointer p, const std::vector<char> *st, const size_t pos): start(p), state(st), position(pos) {}
  228. };
  229. template<typename K, typename T,
  230. typename Hash = std::hash<K>,
  231. typename Pred = std::equal_to<K>,
  232. typename Alloc = allocator<std::pair<const K, T>>>
  233. class hash_map
  234. {
  235. public:
  236. using key_type = K;
  237. using mapped_type = T;
  238. using hasher = Hash;
  239. using key_equal = Pred;
  240. using allocator_type = Alloc;
  241. using value_type = std::pair<const key_type, mapped_type>;
  242. using reference = value_type&;
  243. using const_reference = const value_type&;
  244. using iterator = hash_map_iterator<value_type>;
  245. using const_iterator = hash_map_const_iterator<value_type>;
  246. using size_type = std::size_t;
  247.  
  248. /// Default constructor.
  249. hash_map() = default;
  250.  
  251. ~hash_map() {
  252. alloc.deallocate(data, state.size());
  253. }
  254.  
  255. /**
  256. * @brief Default constructor creates no elements.
  257. * @param n Minimal initial number of buckets.
  258. */
  259. explicit hash_map(size_type n) :
  260. act_size(0), exist_size(0),
  261. data(alloc.allocate(n)),
  262. state(n, 0){}
  263.  
  264. /**
  265. * @brief Builds an %hash_map from a range.
  266. * @param first An input iterator.
  267. * @param last An input iterator.
  268. * @param n Minimal initial number of buckets.
  269. *
  270. * Create an %hash_map consisting of copies of the elements from
  271. * [first,last). This is linear in N (where N is
  272. * distance(first,last)).
  273. */
  274. template<typename InputIterator>
  275. hash_map(InputIterator first, InputIterator last,
  276. size_type n = 0) : hash_map(n) {
  277. insert(first, last);
  278. }
  279.  
  280. /// Copy constructor.
  281. hash_map(const hash_map& other) : hash_map(1) {
  282. alloc = other.getAllocator();
  283. hash = other.hash_function();
  284. equal_key = other.key_eq();
  285. alloc.deallocate(data, bucket_count());
  286. data = alloc.allocate(other.bucket_count());
  287. state = other.state;
  288. for (size_type i = 0; i < state.size(); i++) {
  289. if (state[i] != 0) {
  290. new(data + i) value_type{other.data[i].first, other.data[i].second};
  291. }
  292. }
  293. act_size = other.act_size;
  294. exist_size = other.exist_size;
  295. maxload = other.maxload;
  296. }
  297.  
  298. /// Move constructor.
  299. hash_map(hash_map&& other) : hash_map(1) {
  300. swap(other);
  301. }
  302.  
  303. /**
  304. * @brief Creates an %hash_map with no elements.
  305. * @param a An allocator object.
  306. */
  307.  
  308. explicit hash_map(const allocator_type& a) :
  309. act_size(0), exist_size(0),
  310. state(1, 0), alloc(a),
  311. data(alloc.allocate(1)) {}
  312.  
  313. /*
  314. * @brief Copy constructor with allocator argument.
  315. * @param uset Input %hash_map to copy.
  316. * @param a An allocator object.
  317. */
  318.  
  319. hash_map(const hash_map& umap,
  320. const allocator_type& a) : alloc(a) {
  321. hash = umap.hash_function();
  322. equal_key = umap.key_eq();
  323. data = alloc.allocate(umap.bucket_count());
  324. state = umap.state;
  325. for (size_type i = 0; i < state.size(); i++) {
  326. if (state[i] != 0) {
  327. new(data + i) value_type{umap.data[i].first, umap.data[i].second};
  328. }
  329. }
  330. act_size = umap.act_size;
  331. exist_size = umap.exist_size;
  332. maxload = umap.maxload;
  333. }
  334.  
  335. /*
  336. * @brief Move constructor with allocator argument.
  337. * @param uset Input %hash_map to move.
  338. * @param a An allocator object.
  339. */
  340. hash_map(hash_map&& umap,
  341. const allocator_type& a) : hash_map(1) {
  342. swap(umap);
  343. alloc = a;
  344. }
  345.  
  346. /**
  347. * @brief Builds an %hash_map from an initializer_list.
  348. * @param l An initializer_list.
  349. * @param n Minimal initial number of buckets.
  350. *
  351. * Create an %hash_map consisting of copies of the elements in the
  352. * list. This is linear in N (where N is @a l.size()).
  353. */
  354.  
  355. hash_map(std::initializer_list<value_type> l,
  356. size_type n = 0) : hash_map(n) {
  357. insert(l);
  358. }
  359.  
  360. ///~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  361. /// Copy assignment operator.
  362. hash_map& operator=(const hash_map& other) {
  363. alloc = other.getAllocator();
  364. hash = other.hash_function();
  365. equal_key = other.key_eq();
  366. alloc.deallocate(data, bucket_count());
  367. data = alloc.allocate(other.bucket_count());
  368. state = other.state;
  369. for (size_type i = 0; i < state.size(); i++) {
  370. if (state[i] != 0) {
  371. new(data + i) value_type{other.data[i].first, other.data[i].second};
  372. }
  373. }
  374. act_size = other.act_size;
  375. exist_size = other.exist_size;
  376. maxload = other.maxload;
  377. return *this;
  378. }
  379. ///~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  380. ///~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  381. /// Move assignment operator.
  382. hash_map& operator=(hash_map&& h) {
  383. swap(h);
  384. return *this;
  385. }
  386. ///~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  387.  
  388. /**
  389. * @brief %hash_map list assignment operator.
  390. * @param l An initializer_list.
  391. *
  392. * This function fills an %hash_map with copies of the elements in
  393. * the initializer list @a l.
  394. *
  395. * Note that the assignment completely changes the %hash_map and
  396. * that the resulting %hash_map's size is the same as the number
  397. * of elements assigned.
  398. */
  399.  
  400. ///~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  401. hash_map& operator=(std::initializer_list<value_type> l) {
  402. hash_map res(l.size());
  403. res.insert(l);
  404. *this = res;
  405. return *this;
  406. }
  407. ///~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  408.  
  409. /// Returns the allocator object used by the %hash_map.
  410. allocator_type getAllocator() const noexcept {
  411. return alloc;
  412. }
  413.  
  414. // size and capacity:
  415.  
  416. /// Returns true if the %hash_map is empty.
  417. bool empty() const noexcept {
  418. return exist_size == 0;
  419. }
  420.  
  421. /// Returns the size of the %hash_map.
  422. size_type size() const noexcept {
  423. return exist_size;
  424. }
  425.  
  426. /// Returns the maximum size of the %hash_map.
  427. size_type max_size() const noexcept {
  428. return std::numeric_limits<size_type>::max();
  429. }
  430.  
  431. // iterators.
  432.  
  433. /**
  434. * Returns a read/write iterator that points to the first element in the
  435. * %hash_map.
  436. */
  437. iterator begin() noexcept {
  438. for (size_type i = 0; i < state.size(); i++) {
  439. if (state[i] == 1) {
  440. return iterator(data, &state, i);
  441. }
  442. }
  443. return end();
  444. }
  445.  
  446. //@{
  447. /**
  448. * Returns a read-only (constant) iterator that points to the first
  449. * element in the %hash_map.
  450. */
  451. const_iterator begin() const noexcept {
  452. for (size_type i = 0; i < state.size(); i++) {
  453. if (state[i] == 1) {
  454. return const_iterator(data, &state, i);
  455. }
  456. }
  457. return cend();
  458. }
  459.  
  460. const_iterator cbegin() const noexcept {
  461. for (size_type i = 0; i < state.size(); i++) {
  462. if (state[i] == 1) {
  463. return const_iterator(data, &state, i);
  464. }
  465. }
  466. return cend();
  467. }
  468.  
  469. /**
  470. * Returns a read/write iterator that points one past the last element in
  471. * the %hash_map.
  472. */
  473. iterator end() noexcept {
  474. return iterator(data, &state, state.size());
  475. }
  476.  
  477. //@{
  478. /**
  479. * Returns a read-only (constant) iterator that points one past the last
  480. * element in the %hash_map.
  481. */
  482. const_iterator end() const noexcept {
  483. return const_iterator(data, &state, state.size());
  484. }
  485.  
  486. const_iterator cend() const noexcept {
  487. return const_iterator(data, &state, state.size());
  488. }
  489. //@}
  490.  
  491. // modifiers.
  492.  
  493. /**
  494. * @brief Attempts to build and insert a std::pair into the
  495. * %hash_map.
  496. *
  497. * @param args Arguments used to generate a new pair instance (see
  498. * std::piecewise_contruct for passing arguments to each
  499. * part of the pair constructor).
  500. *
  501. * @return A pair, of which the first element is an iterator that points
  502. * to the possibly inserted pair, and the second is a bool that
  503. * is true if the pair was actually inserted.
  504. *
  505. * This function attempts to build and insert a (key, value) %pair into
  506. * the %hash_map.
  507. * An %hash_map relies on unique keys and thus a %pair is only
  508. * inserted if its first element (the key) is not already present in the
  509. * %hash_map.
  510. *
  511. * Insertion requires amortized constant time.
  512. */
  513.  
  514. template<typename... _Args>
  515. std::pair<iterator, bool> emplace(_Args&&... args) {
  516. auto x = value_type(std::forward<_Args>(args)...);
  517. return insert(x);
  518. }
  519.  
  520. /**
  521. * @brief Attempts to build and insert a std::pair into the
  522. * %hash_map.
  523. *
  524. * @param k Key to use for finding a possibly existing pair in
  525. * the hash_map.
  526. * @param args Arguments used to generate the .second for a
  527. * new pair instance.
  528. *
  529. * @return A pair, of which the first element is an iterator that points
  530. * to the possibly inserted pair, and the second is a bool that
  531. * is true if the pair was actually inserted.
  532. *
  533. * This function attempts to build and insert a (key, value) %pair into
  534. * the %hash_map.
  535. * An %hash_map relies on unique keys and thus a %pair is only
  536. * inserted if its first element (the key) is not already present in the
  537. * %hash_map.
  538. * If a %pair is not inserted, this function has no effect.
  539. *
  540. * Insertion requires amortized constant time.
  541. */
  542. template <typename... _Args>
  543. std::pair<iterator, bool> try_emplace(const key_type& k, _Args&&... args) {
  544. return insert({k, mapped_type(std::forward<_Args>(args)...) });
  545. }
  546. // move-capable overload
  547. template <typename... _Args>
  548. std::pair<iterator, bool> try_emplace(key_type&& k, _Args&&... args) {
  549. return insert({std::move(k), mapped_type(std::forward<_Args>(args)...) });
  550. }
  551.  
  552. //@{
  553. /**
  554. * @brief Attempts to insert a std::pair into the %hash_map.
  555. * @param x Pair to be inserted (see std::make_pair for easy
  556. * creation of pairs).
  557. *
  558. * @return A pair, of which the first element is an iterator that
  559. * points to the possibly inserted pair, and the second is
  560. * a bool that is true if the pair was actually inserted.
  561. *
  562. * This function attempts to insert a (key, value) %pair into the
  563. * %hash_map. An %hash_map relies on unique keys and thus a
  564. * %pair is only inserted if its first element (the key) is not already
  565. * present in the %hash_map.
  566. *
  567. * Insertion requires amortized constant time.
  568. */
  569.  
  570.  
  571. std::pair<iterator, bool> insert(const value_type& x) {
  572. _insert(x);
  573. }
  574.  
  575. std::pair<iterator, bool> insert(value_type&& k) {
  576. _insert(std::move(k));
  577. }
  578.  
  579. //@}
  580.  
  581. /**
  582. * @brief A template function that attempts to insert a range of
  583. * elements.
  584. * @param first Iterator pointing to the start of the range to be
  585. * inserted.
  586. * @param last Iterator pointing to the end of the range.
  587. *
  588. * Complexity similar to that of the range constructor.
  589. */
  590. template<typename _InputIterator>
  591. void insert(_InputIterator first, _InputIterator last) {
  592. for (auto i = first; i != last; ++i) {
  593. insert(*i);
  594. }
  595. }
  596.  
  597. /**
  598. * @brief Attempts to insert a list of elements into the %hash_map.
  599. * @param l A std::initializer_list<value_type> of elements
  600. * to be inserted.
  601. *
  602. * Complexity similar to that of the range constructor.
  603. */
  604. void insert(std::initializer_list<value_type> l) {
  605. insert(l.begin(), l.end());
  606. }
  607.  
  608. /**
  609. * @brief Attempts to insert a std::pair into the %hash_map.
  610. * @param k Key to use for finding a possibly existing pair in
  611. * the map.
  612. * @param obj Argument used to generate the .second for a pair
  613. * instance.
  614. *
  615. * @return A pair, of which the first element is an iterator that
  616. * points to the possibly inserted pair, and the second is
  617. * a bool that is true if the pair was actually inserted.
  618. *
  619. * This function attempts to insert a (key, value) %pair into the
  620. * %hash_map. An %hash_map relies on unique keys and thus a
  621. * %pair is only inserted if its first element (the key) is not already
  622. * present in the %hash_map.
  623. * If the %pair was already in the %hash_map, the .second of
  624. * the %pair is assigned from obj.
  625. *
  626. * Insertion requires amortized constant time.
  627. */
  628. template <typename _Obj>
  629. std::pair<iterator, bool> insert_or_assign(const key_type& k, _Obj&& obj) {
  630. auto d = mapped_type{obj};
  631. if (load_factor() >= max_load_factor() || state.size() == 0) {
  632. rehash((state.size() + 1) * 2);
  633. }
  634.  
  635. auto p = findindex(k);
  636. if (p.first == -1) {
  637. return std::pair<iterator, bool>(end(), false);
  638. }
  639. if (p.second == 0) {
  640. new(data + p.first) value_type{k, d};
  641. exist_size++;
  642. act_size++;
  643. }
  644. else if (p.second == 1) {
  645. data[p.first].second = d;
  646. }
  647. else if (p.second == 2) {
  648. data[p.first].second = d;
  649. exist_size++;
  650. }
  651. state[p.first] = 1;
  652. return std::pair<iterator, bool>(iterator(data, &state, p.first), true);
  653. }
  654.  
  655. // move-capable overload
  656. template <typename _Obj>
  657. std::pair<iterator, bool> insert_or_assign(key_type&& k, _Obj&& obj) {
  658. auto d = mapped_type{obj};
  659. if (load_factor() >= max_load_factor() || state.size() == 0) {
  660. rehash((state.size() + 1) * 2);
  661. }
  662.  
  663. auto p = findindex(std::move(k));
  664. if (p.first == -1) {
  665. return std::pair<iterator, bool>(end(), false);
  666. }
  667. if (p.second == 0) {
  668. new(data + p.first) value_type{k, d};
  669. exist_size++;
  670. act_size++;
  671. }
  672. else if (p.second == 1) {
  673. data[p.first].second = d;
  674. }
  675. else if (p.second == 2) {
  676. data[p.first].second = d;
  677. exist_size++;
  678. }
  679. state[p.first] = 1;
  680. return std::pair<iterator, bool>(iterator(data, &state, p.first), true);
  681. }
  682.  
  683. //@{
  684. /**
  685. * @brief Erases an element from an %hash_map.
  686. * @param position An iterator pointing to the element to be erased.
  687. * @return An iterator pointing to the element immediately following
  688. * @a position prior to the element being erased. If no such
  689. * element exists, end() is returned.
  690. *
  691. * This function erases an element, pointed to by the given iterator,
  692. * from an %hash_map.
  693. * Note that this function only erases the element, and that if the
  694. * element is itself a pointer, the pointed-to memory is not touched in
  695. * any way. Managing the pointer is the user's responsibility.
  696. */
  697. iterator erase(const_iterator position) {
  698. if (bucket((*position).first) == state.size()) {
  699. return end();
  700. }
  701. state[bucket((*position).first)] = 2;
  702. exist_size--;
  703. return position++;
  704. }
  705.  
  706. // LWG 2059.
  707. iterator erase(iterator position) {
  708. if (bucket((*position).first) == state.size()) {
  709. return end();
  710. }
  711. state[bucket((*position).first)] = 2;
  712. exist_size--;
  713. return position++;
  714. }
  715. //@}
  716.  
  717. /**
  718. * @brief Erases elements according to the provided key.
  719. * @param x Key of element to be erased.
  720. * @return The number of elements erased.
  721. *
  722. * This function erases all the elements located by the given key from
  723. * an %hash_map. For an %hash_map the result of this function
  724. * can only be 0 (not present) or 1 (present).
  725. * Note that this function only erases the element, and that if the
  726. * element is itself a pointer, the pointed-to memory is not touched in
  727. * any way. Managing the pointer is the user's responsibility.
  728. */
  729. size_type erase(const key_type& x) {
  730. if (bucket(x) == state.size()) {
  731. return 0;
  732. }
  733. state[bucket(x)] = 2;
  734. exist_size--;
  735. return 1;
  736. }
  737.  
  738. /**
  739. * @brief Erases a [first,last) range of elements from an
  740. * %hash_map.
  741. * @param first Iterator pointing to the start of the range to be
  742. * erased.
  743. * @param last Iterator pointing to the end of the range to
  744. * be erased.
  745. * @return The iterator @a last.
  746. *
  747. * This function erases a sequence of elements from an %hash_map.
  748. * Note that this function only erases the elements, and that if
  749. * the element is itself a pointer, the pointed-to memory is not touched
  750. * in any way. Managing the pointer is the user's responsibility.
  751. */
  752. iterator erase(const_iterator first, const_iterator last) {
  753. for (auto i = first; i != last; i++) {
  754. erase(i);
  755. }
  756. return (iterator)last;
  757. }
  758.  
  759. /**
  760. * Erases all elements in an %hash_map.
  761. * Note that this function only erases the elements, and that if the
  762. * elements themselves are pointers, the pointed-to memory is not touched
  763. * in any way. Managing the pointer is the user's responsibility.
  764. */
  765. void clear() noexcept {
  766.  
  767. state.assign(state.size(), 0);
  768. act_size = 0;
  769. exist_size = 0;
  770. }
  771.  
  772. /**
  773. * @brief Swaps data with another %hash_map.
  774. * @param x An %hash_map of the same element and allocator
  775. * types.
  776. *
  777. * This exchanges the elements between two %hash_map in constant
  778. * time.
  779. * Note that the global std::swap() function is specialized such that
  780. * std::swap(m1,m2) will feed to this function.
  781. */
  782. void swap(hash_map& x) {
  783. using std::swap;
  784. swap(data, x.data);
  785. swap(state, x.state);
  786. swap(act_size, x.act_size);
  787. swap(exist_size, x.exist_size);
  788. swap(maxload, x.maxload);
  789. swap(equal_key, x.equal_key);
  790. swap(hash, x.hash);
  791. swap(alloc, x.alloc);
  792. }
  793.  
  794. template<typename _H2, typename _P2>
  795. void merge(hash_map<K, T, _H2, _P2, Alloc>& source) {
  796. rehash(bucket_count() + source.bucket_count());
  797. insert(source.begin(), source.end());
  798. }
  799.  
  800. template<typename _H2, typename _P2>
  801. void merge(hash_map<K, T, _H2, _P2, Alloc>&& source) {
  802. auto b = std::move(source);
  803. rehash(bucket_count() + b.bucket_count());
  804. insert(b.begin(), b.end());
  805. }
  806.  
  807. // observers.
  808.  
  809. /// Returns the hash functor object with which the %hash_map was
  810. /// constructed.
  811. Hash hash_function() const {
  812. return hash;
  813. }
  814.  
  815. /// Returns the key comparison object with which the %hash_map was
  816. /// constructed.
  817. Pred key_eq() const {
  818. return equal_key;
  819. }
  820.  
  821. // lookup.
  822.  
  823. //@{
  824. /**
  825. * @brief Tries to locate an element in an %hash_map.
  826. * @param x Key to be located.
  827. * @return Iterator pointing to sought-after element, or end() if not
  828. * found.
  829. *
  830. * This function takes a key and tries to locate the element with which
  831. * the key matches. If successful the function returns an iterator
  832. * pointing to the sought after element. If unsuccessful it returns the
  833. * past-the-end ( @c end() ) iterator.
  834. */
  835. iterator find(const key_type& x) {
  836. auto p = findindex(x);
  837. if (p.second == 1) {
  838. return iterator(data, &state, p.first);
  839. }
  840. return end();
  841. }
  842.  
  843. const_iterator find(const key_type& x) const {
  844. auto p = findindex(x);
  845. if (p.second == 1) {
  846. return const_iterator(data, &state, p.first);
  847. }
  848. return cend();
  849. }
  850. //@}
  851.  
  852. /**
  853. * @brief Finds the number of elements.
  854. * @param x Key to count.
  855. * @return Number of elements with specified key.
  856. *
  857. * This function only makes sense for %unordered_multimap; for
  858. * %hash_map the result will either be 0 (not present) or 1
  859. * (present).
  860. */
  861. size_type count(const key_type& x) const {
  862. return contains(x) ? 1 : 0;
  863. }
  864.  
  865. /**
  866. * @brief Finds whether an element with the given key exists.
  867. * @param x Key of elements to be located.
  868. * @return True if there is any element with the specified key.
  869. */
  870. bool contains(const key_type& x) const {
  871. return bucket(x) != state.size();
  872. }
  873.  
  874. //@{
  875. /**
  876. * @brief Subscript ( @c [] ) access to %hash_map data.
  877. * @param k The key for which data should be retrieved.
  878. * @return A reference to the data of the (key,data) %pair.
  879. *
  880. * Allows for easy lookup with the subscript ( @c [] )operator. Returns
  881. * data associated with the key specified in subscript. If the key does
  882. * not exist, a pair with that key is created using default values, which
  883. * is then returned.
  884. *
  885. * Lookup requires constant time.
  886. */
  887. mapped_type& operator[](const key_type& k) {
  888. return _operator(k);
  889. }
  890.  
  891. mapped_type& operator[](key_type&& k) {
  892. return _operator(std::move(k));
  893. }
  894. //@}
  895.  
  896. //@{
  897. /**
  898. * @brief Access to %hash_map data.
  899. * @param k The key for which data should be retrieved.
  900. * @return A reference to the data whose key is equal to @a k, if
  901. * such a data is present in the %hash_map.
  902. * @throw std::out_of_range If no such data is present.
  903. */
  904.  
  905. mapped_type& at(const key_type& k) {
  906. auto p = findindex(k);
  907. if (p.second == 1) {
  908. return data[p.first].second;
  909. }
  910. throw std::out_of_range("");
  911. }
  912.  
  913. const mapped_type& at(const key_type& k) const {
  914. auto p = findindex(std::move(k));
  915. if (p.second == 1) {
  916. return data[p.first].second;
  917. }
  918. throw std::out_of_range("");
  919. }
  920. //@}
  921.  
  922. // bucket interface.
  923.  
  924. /// Returns the number of buckets of the %hash_map.
  925. size_type bucket_count() const noexcept {
  926. return state.size();
  927. }
  928.  
  929. /*
  930. * @brief Returns the bucket index of a given element.
  931. * @param _K A key instance.
  932. * @return The key bucket index.
  933. */
  934. size_type bucket(const key_type& _K) const {
  935. auto p = findindex(_K);
  936. if (p.second == 1) {
  937. return p.first;
  938. }
  939. return state.size();
  940. }
  941.  
  942. // hash policy.
  943.  
  944. /// Returns the average number of elements per bucket.
  945. float load_factor() const noexcept {
  946. if (state.size() == 0) {
  947. return 0;
  948. }
  949. return static_cast<float>(act_size / state.size());
  950. }
  951.  
  952. /// Returns a positive number that the %hash_map tries to keep the
  953. /// load factor less than or equal to.
  954. float max_load_factor() const noexcept {
  955. return maxload;
  956. }
  957.  
  958. /**
  959. * @brief Change the %hash_map maximum load factor.
  960. * @param z The new maximum load factor.
  961. */
  962. void max_load_factor(float z) {
  963. maxload = z;
  964. }
  965.  
  966. /**
  967. * @brief May rehash the %hash_map.
  968. * @param n The new number of buckets.
  969. *
  970. * Rehash will occur only if the new number of buckets respect the
  971. * %hash_map maximum load factor.
  972. */
  973. void rehash(size_type n) {
  974. hash_map res(n);
  975. res.insert(begin(), end());
  976. *this = res;
  977. }
  978.  
  979. /**
  980. * @brief Prepare the %hash_map for a specified number of
  981. * elements.
  982. * @param n Number of elements required.
  983. *
  984. * Same as rehash(ceil(n / max_load_factor())).
  985. */
  986.  
  987. void reserve(size_type n) {
  988. hash_map res(std::ceil(static_cast<float>(n) / static_cast<float>(max_load_factor())));
  989. res.insert(begin(), end());
  990. *this = res;
  991. }
  992.  
  993. bool operator==(const hash_map& other) const {
  994. if (alloc.x != other.alloc.x) {
  995. return false;
  996. }
  997. if (state.size() != other.state.size() || exist_size != other.exist_size) {
  998. return false;
  999. }
  1000. for (size_t i = 0; i < state.size(); i++) {
  1001. if (state[i] == 1 && state[i] != other.state[i]) {
  1002. return false;
  1003. }
  1004. if (state[i] == 1 && other.state[i] == 1) {
  1005. if (!equal_key(data[i].first, other.data[i].first)) {
  1006. return false;
  1007. }
  1008. if (data[i].second != other.data[i].second) {
  1009. return false;
  1010. }
  1011. }
  1012. }
  1013. return true;
  1014. }
  1015.  
  1016. private:
  1017. allocator_type alloc;
  1018. key_equal equal_key;
  1019. hasher hash;
  1020. value_type * data;
  1021. std::vector<char> state;
  1022. size_type act_size = 0;
  1023. size_type exist_size = 0;
  1024. float maxload = 1.0;
  1025.  
  1026. std::pair<int, int> findindex(const key_type& k) const {
  1027. if (state.size() == 0) {
  1028. return std::pair<int, int>(-1, -1);
  1029. }
  1030. const size_type n = hash(k);
  1031. const size_type index = n % state.size();
  1032.  
  1033. size_type i = index;
  1034. while (true) {
  1035. if (state[i] == 0) {
  1036. return std::pair<int, int>(i, 0);
  1037. }
  1038. if (equal_key(data[i].first, k)) {
  1039. if (state[i] == 1) {
  1040. return std::pair<int, int>(i, 1);
  1041. }
  1042. else {
  1043. return std::pair<int, int>(i, 2);
  1044. }
  1045. }
  1046. i++;
  1047. if (i == state.size()) {
  1048. i = 0;
  1049. }
  1050. if (i == index) {
  1051. break;
  1052. }
  1053. }
  1054. return std::pair<int, int>(-1, -1);
  1055. }
  1056.  
  1057. template<typename DDD>
  1058. std::pair<iterator, bool> _insert(DDD&& x) {
  1059. if (load_factor() >= max_load_factor() || state.size() == 0) {
  1060. rehash((state.size() + 1) * 2);
  1061. }
  1062.  
  1063. auto p = findindex(x.first);
  1064. if (p.first == -1) {
  1065. return std::pair<iterator, bool>(end(), false);
  1066. }
  1067. if (p.second == 1) {
  1068. return std::pair<iterator, bool>(iterator(data, &state, p.first), false);
  1069. }
  1070. if (p.second == 0) {
  1071. new(data + p.first) value_type{std::forward<DDD>(x)};
  1072. act_size++;
  1073. }
  1074. else if (p.second == 2) {
  1075. data[p.first].second = std::forward<DDD>(x).second;
  1076. }
  1077. exist_size++;
  1078. state[p.first] = 1;
  1079. return std::pair<iterator, bool>(iterator(data, &state, p.first), true);
  1080. }
  1081.  
  1082. template <typename EEE>
  1083. mapped_type& _operator(EEE&& k) {
  1084. if (load_factor() >= max_load_factor() || state.size() == 0) {
  1085. rehash((state.size() + 1) * 2);
  1086. }
  1087. auto p = findindex(std::forward<EEE>(k));
  1088. if (p.second == 1) {
  1089. return data[p.first].second;
  1090. }
  1091. if (p.second == 0) {
  1092. new(data + p.first) value_type{std::forward<EEE>(k), mapped_type{}};
  1093. state[p.first] = 1;
  1094. act_size++;
  1095. exist_size++;
  1096. return data[p.first].second;
  1097. }
  1098. if (p.second == 2) {
  1099. data[p.first].second = mapped_type{};
  1100. state[p.first] = 1;
  1101. exist_size++;
  1102. return data[p.first].second;
  1103. }
  1104. }
  1105. };
  1106.  
  1107. } // namespace fefu
Add Comment
Please, Sign In to add comment