Sanlover

Untitled

Mar 23rd, 2023
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.19 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4.  
  5. using namespace std;
  6.  
  7. // Определение структуры узла трай-дерева
  8. struct TrieNode
  9. {
  10. // Вектор дочерних узлов (размерность 26 для каждой буквы алфавита)
  11. vector<TrieNode*> children;
  12. // Флаг, указывающий, является ли текущий узел концом слова
  13. bool isEndOfWord;
  14.  
  15. // Конструктор узла трай-дерева, инициализирующий вектор дочерних узлов и флаг конца слова
  16. TrieNode()
  17. {
  18. children = vector<TrieNode*>(26, nullptr);
  19. isEndOfWord = false;
  20. }
  21. };
  22.  
  23. // Класс трай-дерева
  24. class Trie
  25. {
  26. private:
  27. // Указатель на корневой узел трай-дерева
  28. TrieNode* root;
  29.  
  30. public:
  31. // Конструктор трай-дерева, создающий корневой узел
  32. Trie()
  33. {
  34. root = new TrieNode();
  35. }
  36.  
  37. // Метод для добавления слова в трай-дерево
  38. void insert(const string& word)
  39. {
  40. TrieNode* node = root;
  41. // Проходимся по каждой букве слова
  42. for (char c : word)
  43. {
  44. // Если узел не имеет дочернего узла для текущей буквы, создаем его
  45. if (node->children[c - 'a'] == nullptr)
  46. {
  47. node->children[c - 'a'] = new TrieNode();
  48. }
  49. // Переходим к следующему узлу в дочерних узлах
  50. node = node->children[c - 'a'];
  51. }
  52. // Помечаем конечный узел как конец слова
  53. node->isEndOfWord = true;
  54. }
  55.  
  56. // Метод для поиска слова в трай-дереве
  57. bool search(const string& word)
  58. {
  59. TrieNode* node = root;
  60. // Проходимся по каждой букве слова
  61. for (char c : word)
  62. {
  63. // Если узел не имеет дочернего узла для текущей буквы, слова нет в трай-дереве
  64. if (node->children[c - 'a'] == nullptr)
  65. {
  66. return false;
  67. }
  68. // Переходим к следующему узлу в дочерних узлах
  69. node = node->children[c - 'a'];
  70. }
  71. // Проверяем, является ли последний узел концом слова
  72. return node != nullptr && node->isEndOfWord;
  73. }
  74.  
  75. // Метод для поиска слова по префиксу
  76. bool startsWith(const string& prefix)
  77. {
  78. TrieNode* node = root;
  79. // Проходимся по каждой букве префикса
  80. for (char c : prefix)
  81. {
  82. // Если переход к следующему узлу в дочерних узлах невозможен, слова с данным префиксом нет в трай-дереве
  83. if (node->children[c - 'a'] == nullptr)
  84. {
  85. return false;
  86. }
  87. // Переходим к следующему узлу в дочерних узлах
  88. node = node->children[c - 'a'];
  89. }
  90. // Если префикс найден, значит слова в трай-дереве есть с таким префиксом
  91. return node != nullptr;
  92. }
  93.  
  94. // Метод для удаления всех слов с заданным префиксом
  95. void removePrefix(const string& prefix)
  96. {
  97. removePrefixHelper(root, prefix, 0);
  98. deleteEmptyNodes(root);
  99. }
  100.  
  101. private:
  102. // Вспомогательный метод для удаления слов с заданным префиксом
  103. void removePrefixHelper(TrieNode* node, const string& prefix, int index)
  104. {
  105. if (node == nullptr)
  106. {
  107. return;
  108. }
  109. // Если достигли конца префикса, удаляем все слова, начинающиеся с данного префикса
  110. if (index == prefix.length())
  111. {
  112. removeWords(node);
  113. return;
  114. }
  115. // Рекурсивный вызов метода для удаления слов с префиксом
  116. removePrefixHelper(node->children[prefix[index] - 'a'], prefix, index + 1);
  117. }
  118.  
  119. // Вспомогательный метод для удаления всех слов из узла
  120. void removeWords(TrieNode* node)
  121. {
  122. if (node == nullptr)
  123. {
  124. return;
  125. }
  126. // Сбрасываем флаг конца слова
  127. node->isEndOfWord = false;
  128. // Рекурсивный вызов метода для удаления всех слов из дочерних узлов
  129. for (int i = 0; i < node->children.size(); i++)
  130. {
  131. removeWords(node->children[i]);
  132. }
  133. // Удаляем текущий узел
  134. delete node;
  135. }
  136.  
  137. // Вспомогательный метод для удаления пустых узлов из трай-дерева
  138. void deleteEmptyNodes(TrieNode* node)
  139. {
  140. if (node == nullptr)
  141. {
  142. return;
  143. }
  144. // Рекурсивный вызов метода для удаления пустых узлов из дочерних узлов
  145. for (int i = 0; i < node->children.size(); i++)
  146. {
  147. if (node->children[i] != nullptr)
  148. {
  149. // Если у дочернего узла нет флага конца слова и он пуст, удаляем его
  150. if (node->children[i]->isEndOfWord == false && isNodeEmpty(node->children[i]))
  151. {
  152. delete node->children[i];
  153. node->children[i] = nullptr;
  154. }
  155. else
  156. {
  157. deleteEmptyNodes(node->children[i]);
  158. }
  159. }
  160. }
  161. }
  162.  
  163.  
  164. // Метод для проверки, является ли узел пустым
  165. bool isNodeEmpty(TrieNode* node)
  166. {
  167. // Проходимся по всем дочерним узлам текущего узла
  168. for (TrieNode* child : node->children)
  169. {
  170. // Если дочерний узел не равен nullptr, значит он не пустой
  171. if (child != nullptr)
  172. {
  173. // Так как наша задача - удалить все пустые узлы, то если нашли хотя бы один непустой узел,
  174. // можно сразу вернуть false - текущий узел не является пустым
  175. return false;
  176. }
  177. }
  178. // Если цикл прошел по всем дочерним узлам, и ни один из них не был непустым, значит текущий узел пустой
  179. return true;
  180. }
  181. };
  182.  
  183.  
  184. int main()
  185. {
  186. Trie trie;
  187. // Вставляем
  188. trie.insert("apple");
  189. trie.insert("banana");
  190. trie.insert("app");
  191. trie.insert("apartment");
  192. trie.insert("baby");
  193. trie.insert("book");
  194. // Удаляем с префиксом "ap"
  195. trie.removePrefix("ap");
  196. // Проверяем наличие слов в дереве с помощью поиска
  197. cout << (trie.search("apple") ? "apple found" : "apple not found") << endl;
  198. cout << (trie.search("banana") ? "banana found" : "banana not found") << endl;
  199. cout << (trie.search("app") ? "app found" : "app not found") << endl;
  200. cout << (trie.search("apartment") ? "apartment found" : "apartment not found") << endl;
  201. cout << (trie.search("baby") ? "baby found" : "baby not found") << endl;
  202. cout << (trie.search("book") ? "book found" : "book not found") << endl;
  203. return 0;
  204. }
  205.  
Add Comment
Please, Sign In to add comment