Advertisement
Guest User

Untitled

a guest
Nov 20th, 2019
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.31 KB | None | 0 0
  1. #ifndef ADS_SET_H
  2. #define ADS_SET_H
  3.  
  4. #include <functional>
  5. #include <algorithm>
  6. #include <iostream>
  7. #include <stdexcept>
  8. #include <cmath>
  9. #include <stdexcept>
  10. #include <vector>
  11.  
  12. template <typename Key, size_t N = 7>
  13. class ADS_set {
  14. public:
  15. class Iterator;
  16. using value_type = Key;
  17. using key_type = Key;
  18. using reference = key_type &;
  19. using const_reference = const key_type &;
  20. using size_type = size_t;
  21. using difference_type = std::ptrdiff_t;
  22. using iterator = Iterator;
  23. using const_iterator = Iterator;
  24. using key_compare = std::less<key_type>; // B+-Tree
  25. using key_equal = std::equal_to<key_type>; // Hashing
  26. using hasher = std::hash<key_type>; // Hashing
  27.  
  28. private:
  29. enum class Mode {free, used, freeagain, end};
  30. struct element {
  31. key_type key;
  32. Mode mode {Mode::free};
  33. element *next {nullptr};
  34. };
  35. element *table {nullptr};
  36. element *last_ptr {nullptr};
  37. element *keller{nullptr};
  38. size_type table_size {0}, curr_size {0};
  39. float max_lf {0.5};
  40. size_type hash_idx(const key_type &key) const { return hasher{}(key) % static_cast<size_t>(ceil(table_size*max_lf)); }
  41. void reserve(size_type n);
  42. void rehash(size_type n);
  43. element *insert_(const key_type &key);
  44. element *find_(const key_type &key) const;
  45. public:
  46. ADS_set() { rehash(N); }
  47. ADS_set(std::initializer_list<key_type> ilist): ADS_set{} { insert(ilist); }
  48. template<typename InputIt> ADS_set(InputIt first, InputIt last): ADS_set{} { insert(first,last); }
  49. ADS_set(const ADS_set &other): ADS_set{} {
  50. reserve(other.curr_size);
  51. for (const auto &k: other) {
  52. insert_(k);
  53. }
  54. }
  55.  
  56. ~ADS_set() { delete[] table; }
  57.  
  58.  
  59. ADS_set &operator=(const ADS_set &other) {
  60. if (this == &other) return *this;
  61. ADS_set tmp{other};
  62. swap(tmp);
  63. return *this;
  64. }
  65. ADS_set &operator=(std::initializer_list<key_type> ilist) {
  66. ADS_set tmp{ilist};
  67. swap(tmp);
  68. return *this;
  69. }
  70.  
  71. size_type size() const { return curr_size; }
  72. bool empty() const { return curr_size == 0; }
  73.  
  74. size_type count(const key_type &key) const { return !!find_(key); }
  75. iterator find(const key_type &key) const {
  76. if (auto p {find_(key)}) return iterator{p};
  77. return end();
  78. }
  79.  
  80. void clear() {
  81. ADS_set tmp;
  82. swap(tmp);
  83. }
  84. void swap(ADS_set &other) {
  85. using std::swap;
  86. swap(table, other.table);
  87. swap(curr_size, other.curr_size);
  88. swap(table_size, other.table_size);
  89. swap(last_ptr, other.last_ptr);
  90. swap(keller, other.keller);
  91. swap(max_lf, other.max_lf);
  92. }
  93.  
  94. void insert(std::initializer_list<key_type> ilist) { insert(std::begin(ilist), std::end(ilist)); }
  95. std::pair<iterator,bool> insert(const key_type &key) {
  96. if (auto p {find_(key)}) return {iterator{p},false};
  97. reserve(curr_size+1);
  98. return {iterator{insert_(key)},true};
  99. }
  100.  
  101. template<typename InputIt> void insert(InputIt first, InputIt last);
  102.  
  103.  
  104. size_type erase(const key_type &key){
  105. if(find_(key) == nullptr){
  106. return 0;
  107. }
  108.  
  109. element* current = table + hash_idx(key);
  110. element* follow {nullptr};
  111. element* previous{nullptr};
  112.  
  113. //if(current->mode != Mode::used) return 0;
  114.  
  115. if(key_equal{}(current->key, key)){
  116. if(current->next == nullptr) current->mode = Mode::freeagain;
  117. else{
  118. follow = current->next;
  119. current->key = follow->key;
  120. current->next = follow->next;
  121. follow->mode = Mode::freeagain;
  122.  
  123. if(follow > last_ptr) last_ptr = follow;
  124. }
  125. --curr_size;
  126. }else{
  127. previous = current;
  128. current = previous->next;
  129. follow = current->next;
  130.  
  131. while(current != nullptr) {
  132.  
  133. if(key_equal{}(current->key, key)) {
  134. follow = current->next;
  135. previous->next = follow;
  136. current->mode = Mode::freeagain;
  137. break;}
  138.  
  139. previous = current;
  140. current = previous->next;
  141.  
  142. }
  143.  
  144. if(current > last_ptr) last_ptr = current;
  145. --curr_size;
  146. }
  147.  
  148. return 1;
  149. }
  150.  
  151. const_iterator begin() const { return const_iterator{table}; }
  152. const_iterator end() const { return const_iterator{table+table_size}; }
  153.  
  154. void dump(std::ostream &o = std::cerr) const;
  155.  
  156. friend bool operator==(const ADS_set &lhs, const ADS_set &rhs) {
  157. if (lhs.curr_size != rhs.curr_size) return false;
  158. for (const auto &k: rhs) if (!lhs.count(k)) return false;
  159. return true;
  160. }
  161. friend bool operator!=(const ADS_set &lhs, const ADS_set &rhs) { return !(lhs == rhs); }
  162.  
  163.  
  164. };
  165.  
  166. template <typename Key, size_t N>
  167. typename ADS_set<Key,N>::element *ADS_set<Key,N>::insert_(const key_type &key) {
  168. reserve(curr_size + 1);
  169. size_type idx {hash_idx(key)};
  170.  
  171. if(table[idx].mode != Mode::used){
  172. table[idx].key = key;
  173. table[idx].mode = Mode::used;
  174. ++curr_size;
  175.  
  176. return table+idx;
  177. }else {
  178. element *help = table + idx;
  179. while(help->next != nullptr) help = help->next;
  180. help->next = last_ptr;
  181. last_ptr->key = key;
  182. last_ptr->mode = Mode::used;
  183. last_ptr->next = nullptr;
  184. help = last_ptr;
  185.  
  186. while(last_ptr->mode == Mode::used && last_ptr != keller) { --last_ptr; }
  187.  
  188. ++curr_size;
  189.  
  190. return help;
  191. }
  192. }
  193.  
  194. template <typename Key, size_t N>
  195. typename ADS_set<Key,N>::element *ADS_set<Key,N>::find_(const key_type &key) const {
  196. element * help = table + hash_idx(key);
  197.  
  198. if(help->mode == Mode::used){
  199. if(key_equal{}(help->key, key)) return help;
  200.  
  201. else{
  202. while(help != nullptr) {
  203. if(key_equal{}(help->key, key)) {return help;}
  204. else help = help->next;
  205. }
  206. }
  207. }
  208. return nullptr;
  209. }
  210.  
  211. template <typename Key, size_t N>
  212. template<typename InputIt> void ADS_set<Key,N>::insert(InputIt first, InputIt last) {
  213. for (auto it {first}; it != last; ++it) {
  214. if (!count(*it)) {
  215. reserve(curr_size + 1);
  216. insert_(*it);
  217. }
  218. }
  219. }
  220.  
  221.  
  222. template <typename Key, size_t N>
  223. void ADS_set<Key,N>::reserve(size_type n) {
  224. if(n > table_size * max_lf || last_ptr == keller) {
  225. size_type new_table_size { table_size};
  226. do{
  227. new_table_size = new_table_size * 2 + 1;
  228. } while(n > new_table_size * max_lf);
  229. rehash(new_table_size);
  230. }
  231. }
  232.  
  233. template <typename Key, size_t N>
  234. void ADS_set<Key,N>::rehash(size_type n) {
  235. size_type new_table_size {std::max(N, std::max(n,size_type(curr_size / max_lf)))};
  236. element *new_table {new element[new_table_size+1]};
  237. new_table[new_table_size].mode = Mode::end;
  238. size_type old_table_size {table_size};
  239. element *old_table {table};
  240. curr_size = 0;
  241. table = new_table;
  242. table_size = new_table_size;
  243. keller = table + static_cast<size_type>(floor(table_size*max_lf));
  244. last_ptr = table + table_size - 1;
  245. for (size_type idx{0}; idx < old_table_size; ++idx) {
  246. if (old_table[idx].mode == Mode::used) insert_(old_table[idx].key);
  247. }
  248. delete[] old_table;
  249. }
  250.  
  251. template <typename Key, size_t N>
  252. void ADS_set<Key,N>::dump(std::ostream &o) const {
  253. o << "curr_size = " << curr_size << " table_size = " << table_size << "\n";
  254. for(size_type idx{0}; idx < table_size + 1; ++idx) {
  255. o << idx << " : ";
  256. switch (table[idx].mode) {
  257. case Mode::free:
  258. o << "..free";
  259. break;
  260. case Mode::used:
  261. o << table[idx].key;
  262. break;
  263. case Mode::freeagain:
  264. o << "..freeagain";
  265. break;
  266. case Mode::end:
  267. o << "..END";
  268. break;
  269.  
  270. }
  271. o << "\n";
  272. }
  273. }
  274.  
  275.  
  276. template <typename Key, size_t N>
  277. class ADS_set<Key,N>::Iterator {
  278. public:
  279. using value_type = Key;
  280. using difference_type = std::ptrdiff_t;
  281. using reference = const value_type &;
  282. using pointer = const value_type *;
  283. using iterator_category = std::forward_iterator_tag;
  284.  
  285. private:
  286. element *pos;
  287. void skip() { while (pos->mode != Mode::used && pos->mode != Mode::end) ++pos; }
  288.  
  289. public:
  290. explicit Iterator(element *pos = nullptr): pos{pos} { if (pos) skip(); }
  291. reference operator*() const { return pos->key; }
  292. pointer operator->() const { return &pos->key; }
  293. Iterator &operator++() { ++pos; skip(); return *this; }
  294. Iterator operator++(int) { auto rc {*this}; ++*this; return rc; }
  295. friend bool operator==(const Iterator &lhs, const Iterator &rhs) { return lhs.pos == rhs.pos; }
  296. friend bool operator!=(const Iterator &lhs, const Iterator &rhs) { return !(lhs == rhs); }
  297. };
  298.  
  299. template <typename Key, size_t N> void swap(ADS_set<Key,N> &lhs, ADS_set<Key,N> &rhs) { lhs.swap(rhs); }
  300.  
  301. #endif // ADS_SET_H
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement