Advertisement
Guest User

Untitled

a guest
Dec 13th, 2018
678
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.98 KB | None | 0 0
  1. /*
  2. Реализуйте структуру данных типа “множество строк” на основе динамической хеш-таблицы с открытой адресацией.
  3. Хранимые строки непустые и состоят из строчных латинских букв.
  4. Хеш-функция строки должна быть реализована с помощью вычисления значения многочлена методом Горнера.
  5. Начальный размер таблицы должен быть равным 8-ми.
  6. Перехеширование выполняйте при добавлении элементов в случае, когда коэффициент заполнения таблицы достигает 3/4.
  7. Структура данных должна поддерживать операции добавления строки в множество, удаления строки из множества и проверки принадлежности данной строки множеству.
  8. 1_1. Для разрешения коллизий используйте квадратичное пробирование. i-ая проба g(k, i)=g(k, i-1) + i (mod m). m - степень двойки.
  9.  
  10. Идея решения:
  11. Реализована хеш-функция и соответсвующая хеш-таблица. Хеш функция вычисляется методом Горнера.
  12. Причем константа - число, взаимно простое с размером таблицы, который всегда будет степенью двойки.
  13. таким образом хеш-функция может принимать все значения по модулю размера таблицы.
  14. А значит шанс возникновения коллизий уменьшается.
  15.  
  16. Описан класс Хеш-таблица со след типичными методами:
  17. find. Ищем элемент. Достаточно пройтись до первой свободной ячейки. Мы гарантированно пройдем
  18. все ячейки хеш-функции с помощью квадратичного пробирования(оно нам это и гарантирует).
  19. Поэтому останавливаемся, когда элемент найден или прошли n шагов.
  20. erase. Ищем искомый элемент тем же квадратичным пробированием, и ставим ячейку DELETED.
  21. insert. Вставляем элемент только в пустую ячейку.( До этого квадратичным пробированием проверяя наличие
  22. элемента в таблице.
  23. grow. - Расширение таблицы. Понадобится, когда коэффициент заполнения не станет больше 0,75.
  24. Делается для того, чтобы последующие операции вставки, удаления, поиска проходили за более
  25. короткое время.
  26. (Для себя). Стоит отметить, что квадратичное пробирование не такое уж и эффективное, потому
  27. что для элементов с одинаковыми хеш-функциями последовательность проб будет одна и та же.
  28. (Всего различных последовательностей проб - m из возможных m!)
  29. А вот двойное хеширование немножко смягчает эту проблему: вероятность коллизии при вычислении
  30. двух хешов значителльно уменьшается.( Всего различных последовательностей проб м.б. m^2 из
  31. возможных n!)
  32. А насчет линейного пробирования совсем уж плохо. Образуются огромные кластеры подряд идущих
  33. элементов, поэтому для некоторых элементов за счет увелечения размера кластера вероятность
  34. попадания при следующей пробе достаточно велика.
  35.  
  36. */
  37.  
  38.  
  39. #include<iostream>
  40. #include<vector>
  41. #include<string>
  42. #include<cmath>
  43.  
  44. using std::vector;
  45. using std::string;
  46. const int a = 173099;
  47.  
  48. int Hash_Function(string s, int table_size)
  49. {
  50. int hash = s[0] % table_size;
  51. for (auto item = s.begin() + 1; item != s.end(); ++item)
  52. hash = (hash*a + *item) % table_size;
  53. return hash;
  54. }
  55.  
  56. class HashTable {
  57. public:
  58. HashTable(int size_) : table(size_), size(0) {
  59. for (int i = 0; i < table.size(); ++i)
  60. table[i] = " ";
  61. };
  62. bool Insert(string s)
  63. {
  64. if (4 * size >= table.size() * 3)
  65. grow();
  66. int hash = Hash_Function(s, table.size());
  67. for (int i = 0; i < table.size(); ++i)
  68. {
  69. hash = (hash + i) % table.size();
  70. //std::cout << s << '\t' <<hash << '\n';
  71. if (table[hash] == " ")
  72. {
  73. table[hash] = s;
  74. break;
  75. }
  76. if (table[hash] == s)
  77. return false;
  78. }
  79. ++size;
  80. return true;
  81. }
  82. bool erase(string s)
  83. {
  84. int n = table.size();
  85. int hash = Hash_Function(s, table.size());
  86. for (int i = 0; ; ++i)
  87. {
  88. hash = (hash + i) % table.size();
  89. if (table[hash] == s)
  90. {
  91. table[hash] = "DELETED";
  92. return true;
  93. }
  94. if (table[hash] == " ")
  95. return false;
  96. }
  97. return false;
  98. }
  99. bool find(string s)
  100. {
  101. int n = table.size();
  102. int hash = Hash_Function(s, table.size());
  103. for (int i = 0; ; ++i)
  104. {
  105. hash = (hash + i) % table.size();
  106. if (table[hash] == s)
  107. return true;
  108. if (table[hash] == " ")
  109. return false;
  110. }
  111. }
  112. private:
  113. vector<std::string> table;
  114. int size;
  115. void grow()
  116. {
  117. //std::cout << "grow" << '\n';
  118. vector<string> New_Table(table.size() * 2);
  119. for (int i = 0; i < New_Table.size(); ++i) // cannot i use this . Can i use Hash_Table?
  120. New_Table[i] = " ";
  121. int size1 = 0;
  122. for (int i = 0; i < table.size(); ++i)
  123. if (table[i] != "DELETED" && table[i] != " ")
  124. {
  125. int hash = Hash_Function(table[i], New_Table.size());
  126. for (int j = 0; ; ++j)
  127. {
  128. hash = (hash + j) % New_Table.size();
  129. if (New_Table[hash] == " ")
  130. {
  131. ++size1;
  132. New_Table[hash] = table[i];
  133. break;
  134. }
  135. }
  136. }
  137. table = New_Table;
  138. size = size1;
  139. }
  140. };
  141. int main()
  142. {
  143. HashTable tb(8);
  144. string c;
  145. while (std::cin >> c)
  146. {
  147. string s;
  148. std::cin >> s;
  149. if (c == "+")
  150. {
  151. if (tb.Insert(s) == 1)
  152. std::cout << "OK" << '\n';
  153. else std::cout << "FAIL" << '\n';
  154. continue;
  155. }
  156. if (c == "?")
  157. {
  158. if (tb.find(s) == 1)
  159. std::cout << "OK" << '\n';
  160. else std::cout << "FAIL" << '\n';
  161. continue;
  162. }
  163. if (tb.erase(s) == 1)
  164. std::cout << "OK" << '\n';
  165. else std::cout << "FAIL" << '\n';
  166. }
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement