Advertisement
lezsakdomi

Trie.hpp

May 11th, 2021
555
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.51 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <string>
  4. #include <algorithm>
  5. #include <array>
  6.  
  7. const int ALPHABET_SIZE = 26;
  8.  
  9. template<class T, class U>
  10. class TrieBase {
  11. private:
  12.     bool isEndOfWord = false;
  13.     U meaning = NULL;
  14.  
  15. protected:
  16.     int characterSize;
  17.     TrieBase<T, U> **character;
  18.  
  19.     explicit TrieBase(int characterSize) : characterSize(characterSize),
  20.                                            character(new TrieBase<T, U> *[characterSize]) {
  21.         for (size_t i = 0; i < characterSize; i++) {
  22.             character[i] = nullptr;
  23.         }
  24.     }
  25.  
  26. public:
  27.     bool haveChildren() const {
  28.         for (size_t i = 0; i < characterSize; i++) {
  29.             if (this->character[i]) {
  30.                 return true;
  31.             }
  32.         }
  33.         return false;
  34.     }
  35.  
  36.     U getMeaning() const {
  37.         return meaning;
  38.     }
  39.  
  40.     void setMeaning(const U &newMeaning) {
  41.         if (this->isEndOfWord) {
  42.             throw std::runtime_error("Trie already has a meaning");
  43.         } else {
  44.             this->isEndOfWord = true;
  45.             this->meaning = newMeaning;
  46.         }
  47.     }
  48.  
  49.     bool getIsEndOfWord() const {
  50.         return isEndOfWord;
  51.     }
  52.  
  53.     TrieBase<T, U> &operator=(const TrieBase<T, U> &rhs) {
  54.         if (this != &rhs) {
  55.             for (size_t i = 0; i < this->characterSize; i++) {
  56.                 if (rhs.character[i] != nullptr) {
  57.                     this->character[i] = rhs.character[i];
  58.                 }
  59.             }
  60.         }
  61.  
  62.         return *this;
  63.     }
  64.  
  65.     TrieBase<T, U> &operator+=(const TrieBase<T, U> &rhs) {
  66.         if (this != &rhs) {
  67.             for (size_t i = 0; i < this->characterSize /* == rhs.characterSize */; i++) {
  68.                 if (rhs.character[i] == nullptr) {
  69.                     // noop
  70.                 } else {
  71.                     if (this->character[i] == nullptr) {
  72.                         this->character[i] = new TrieBase<T, U>(characterSize);
  73.                         this->character[i] = *rhs.character[i];
  74.                     } else {
  75.                         this->character[i] += *rhs.character[i];
  76.                     }
  77.                 }
  78.             }
  79.         }
  80.  
  81.         return *this;
  82.     }
  83.  
  84.     virtual ~TrieBase() {
  85.         for (size_t i = 0; i < characterSize; i++) {
  86.             if (character[i] == nullptr)
  87.                 delete character[i];
  88.         }
  89.     }
  90. };
  91.  
  92. class TrieInt : public TrieBase<int, int> {
  93. private:
  94.     static int arraySize(int n) {
  95.         int db = 1;
  96.         while (n >= 2) {
  97.             n /= 2;
  98.             db++;
  99.         }
  100.         return db;
  101.     }
  102.  
  103.     static int getBit(const int &n, const size_t &i) {
  104.         // magic
  105.         return (n >> i) % 2;
  106.     }
  107.  
  108. public:
  109.     TrieInt() : TrieBase<int, int>(2) {} // NOLINT(modernize-use-equals-default)
  110.  
  111.     ~TrieInt() override {} // NOLINT(modernize-use-equals-default)
  112.  
  113.     void newWord(const int &word, const int &meaning) {
  114.         TrieInt *currentTree = this;
  115.  
  116.         for (size_t i = 0; i < TrieInt::arraySize(meaning); i++) {
  117.             const int pos = TrieInt::getBit(word, i);
  118.             if (currentTree->character[pos] == nullptr) {
  119.                 currentTree->character[pos] = new TrieInt();
  120.             }
  121.             currentTree = (TrieInt *) currentTree->character[pos];
  122.         }
  123.  
  124.         currentTree->setMeaning(meaning);
  125.     }
  126.  
  127.     int getMeaning(const int &word) const {
  128.         TrieInt const *currentTree = this;
  129.  
  130.         for (size_t i = 0; i < TrieInt::arraySize(word); i++) {
  131.             const int pos = TrieInt::getBit(word, i);
  132.             currentTree = (TrieInt *) currentTree->character[pos];
  133.             if (currentTree == nullptr) {
  134.                 throw std::runtime_error("The word has no meaning");
  135.             }
  136.         }
  137.  
  138.         if (currentTree->getIsEndOfWord()) return currentTree->getMeaning();
  139.         else throw std::runtime_error("The word is not a meaning");
  140.     }
  141.  
  142. //    void makeNewTrie(TrieInt<T> &node) {
  143. //        this->insert(node.isEndOfWord, node.meaning);
  144. //
  145. //        for (size_t i = 0; i < BINARY_SIZE; i++) {
  146. //            if (node.character[i] != nullptr)
  147. //                makeNewTrie(node);
  148. //        }
  149. //    }
  150.  
  151.     void deleteWord(const int &word) {
  152.         auto **thisPointer = new TrieInt *(this);
  153.         TrieInt **currentTreePointer = thisPointer;
  154.  
  155.         for (size_t i = 0; i < TrieInt::arraySize(word); i++) {
  156.             TrieInt *&currentTree = *currentTreePointer;
  157.  
  158.             if (currentTree == nullptr) {
  159.                 throw std::runtime_error("The word has no meaning");
  160.             }
  161.  
  162.             if (currentTree->getIsEndOfWord()) {
  163.                 delete currentTree;
  164.                 currentTree = nullptr;
  165.             }
  166.  
  167.             const int pos = TrieInt::getBit(word, i);
  168.             if (currentTree->character[1 - pos] == nullptr) {
  169.                 delete currentTree->character[pos];
  170.                 currentTree->character[pos] = nullptr;
  171.  
  172.                 if (this != currentTree) {
  173.                     delete currentTree;
  174.                     currentTree = nullptr;
  175.                 }
  176.  
  177.                 return;
  178.             }
  179.  
  180.             currentTreePointer = &(TrieInt *) currentTree->character[pos];
  181.         }
  182.  
  183.         delete thisPointer;
  184.     }
  185. };
  186.  
  187. class TrieChar : public TrieBase<char, std::string> {
  188.     TrieChar<T> *character[ALPHABET_SIZE];
  189. public:
  190.     TrieChar() {
  191.         for (size_t i = 0; i < ALPHABET_SIZE; i++) {
  192.             character[i] = nullptr;
  193.         }
  194.     }
  195.  
  196.     TrieChar(const TrieChar &other) {
  197.         TrieChar<T> node = other;
  198.         makeNewTrie(node);
  199.     }
  200.  
  201.     ~TrieChar() {
  202.         for (size_t i = 0; i < ALPHABET_SIZE; i++) {
  203.             if (character[i] == nullptr)
  204.                 delete character[i];
  205.         }
  206.     }
  207.  
  208.     void newWord(const std::string &str, const T *pMeaning) {
  209.         TrieChar<T> *temp = this;
  210.         for (size_t i = 0; i < str.length(); i++) {
  211.             if (temp->character[str[i] - 'a'] == nullptr)
  212.                 temp->character[str[i] - 'a'] = new TrieChar<T>();
  213.             temp = temp->character[str[i] - 'a'];
  214.         }
  215.         temp->isEndOfWord = true;
  216.         temp->meaning = new char[str.length()];
  217.         for (size_t i = 0; i < ((std::string) pMeaning).length() + 1; i++) {
  218.             temp->meaning[i] = pMeaning[i];
  219.         }
  220.     }
  221.  
  222.     bool haveChildren() const {
  223.         for (size_t i = 0; i < ALPHABET_SIZE; i++) {
  224.             if (this->character[i]) {
  225.                 return true;
  226.             }
  227.         }
  228.         return false;
  229.     }
  230.  
  231.     bool haveChildren(const TrieChar<T> *curr) const {
  232.         for (size_t i = 0; i < ALPHABET_SIZE; i++) {
  233.             if (curr->character[i]) {
  234.                 return true;
  235.             }
  236.         }
  237.         return false;
  238.     }
  239.  
  240.     const T *getMeaning(const std::string &str) const {
  241.         const TrieChar<T> *temp = this;
  242.         for (size_t i = 0; i < str.length(); i++) {
  243.             temp = temp->character[str[i] - 'a'];
  244.             if (temp == nullptr)
  245.                 return " ";
  246.         }
  247.  
  248.         if (temp->isEndOfWord)
  249.             return temp->meaning;
  250.         return " ";
  251.     }
  252.  
  253.     void makeNewTrie(TrieChar<T> &node) {
  254.         this->insert(node.getIsEndOfWord(), node.getMeaning());
  255.  
  256.         for (size_t i = 0; i < ALPHABET_SIZE; i++) {
  257.             if (node.character[i] != nullptr)
  258.                 makeNewTrie(node);
  259.         }
  260.     }
  261.  
  262.     void search(TrieChar<T> *&curr, const std::string &key, TrieChar<T> *&parent) {
  263.         for (size_t i = 0; i < key.length(); i++) {
  264.             for (size_t j = 0; j < ALPHABET_SIZE; j++) {
  265. //              if (curr->character[j] == key[i])
  266.                 {
  267.                     parent = curr;
  268.                     curr = curr->character[i];
  269.                     break;
  270.                 }
  271.             }
  272.         }
  273.     }
  274.  
  275.     bool deleteWord(TrieChar<T> *&root, const std::string &key) {
  276.         TrieChar<T> *parent = nullptr;
  277.         TrieChar<T> *curr = root;
  278.         search(curr, key, parent);
  279.         if (curr == nullptr)
  280.             return false;
  281.         if (haveChildren(curr)) {
  282.             curr->isEndOfWord = false;
  283.             curr->meaning = NULL;
  284.             return true;
  285.         }
  286.         while (!haveChildren(curr)) {
  287.             if (curr != root) {
  288.                 for (size_t i = 0; i < ALPHABET_SIZE; i++) {
  289.                     if (parent->character[i] == curr)
  290.                         parent->character[i] = nullptr;
  291.                 }
  292.             } else
  293.                 root = nullptr;
  294.             delete root;
  295.             curr = parent;
  296.             //parent = &curr; //wrong
  297.         }
  298.         return true;
  299.     }
  300.  
  301.     TrieChar<T> &operator=(const TrieChar<T> &rhs) {
  302.         if (this != &rhs) {
  303.             for (size_t i = 0; i < ALPHABET_SIZE; i++) {
  304.                 if (rhs.character[i] != nullptr) {
  305.                     delete this->character[i];
  306.                     this->character[i] = new TrieChar<T>();
  307.                     this->character[i] = rhs.character[i];
  308.                 }
  309.             }
  310.         }
  311.         return *this;
  312.     }
  313.  
  314.     TrieChar<T> &operator+(const TrieChar<T> &rhs) {
  315.         if (this != &rhs) {
  316.             for (size_t i = 0; i < ALPHABET_SIZE; i++) {
  317.                 if (this->character[i] != nullptr && rhs.character[i] == nullptr) {
  318.                     this->character[i] = new TrieChar<T>();
  319.                     this->character[i] = rhs.character[i];
  320.                 }
  321.             }
  322.         }
  323.         return *this;
  324.     }
  325.  
  326.     TrieChar<T> &operator+=(const TrieChar<T> &rhs) {
  327.         return *this = *this + rhs;
  328.     }
  329. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement