📜  在C++中使用智能指针和OOP进行Trie数据结构

📅  最后修改于: 2021-04-17 09:11:16             🧑  作者: Mango

我们将在C++和OOP中使用智能指针来实现trie。在这里,我们已经讨论了使用递归实现trie数据的方法

在我们的实现节点中,特里看起来像:

class TrieNode{
  
    public:
    // Use of shared_ptr for storing Children 
    // Pointers of TrieNode
  
    shared_ptr children[ALPHABET_SIZE];
  
    // Tracks whether If this Node is the end of 
    // any word stored in Trie
  
    bool isWord;
  
    // Constructor for TrieNode
    TrieNode()
    {
        for(int i=0; i

接口是显示我们的对象类的功能的类,该对象类仅具有纯虚函数。在这里,概念界面将进行更详细的讨论。

// Interface representing functionalities 
// of Trie Data Structure
class interface {
public:
    interface() {}
    virtual ~interface() {}
    // Pure virtual functions showing all 
    // the functions of my Trie class
   
    // To convert character to integer like hashing
    virtual int i2c(char) = 0;
   
    // Inserts word to Trie
    virtual void insertWord(string&) = 0;
   
    // Deletes word if present
    virtual bool deleteWord(string&) = 0;
   
    // To search a word in Trie
    virtual bool searchWord(string&) = 0;
   
    // Checks whether there is any children present
    // for any node
    virtual bool isEmptyNode(shared_ptr) 
                                          const = 0;
};

nullptrs存储NULL,这表明该位置的其他任何字符串都没有路径

下图显示了将“怪胎”插入空的特里。

下图显示了将“ geeksfor”插入到特里。怪胎p已经退出了。因此,它重叠。

下图显示了将“ trie”插入到trie中

为什么要使用shared_ptr而不是所有其他智能指针(auto_ptr,unique_ptr,weak_ptr)?

由于在构造Trie时可能会遇到这样的情况,我们可能不得不共享指向另一个临时shared_ptr的特定指针的资源以遍历Trie的事实,所以我们使用了shared_ptr 。在这一点上,shared_ptr优于上面提到的任何其他指针。

下面是上述方法的实现:

#include 
  
// For shared_ptr class
#include  
  
using namespace std;
#define ALPHABET_SIZE 26
  
// Trie Node class
class TrieNode {
  
public:
    // Use of shared_ptr for storing Children
    // Pointers of TrieNode
  
    shared_ptr children[ALPHABET_SIZE];
  
    // Tracks whether If this Node is the end of
    // any word stored in Trie
  
    bool isWord;
  
    // Constructor for TrieNode
    TrieNode()
    {
        for (int i = 0; i < ALPHABET_SIZE; i++) {
            children[i] = shared_ptr();
        }
        isWord = false;
    }
};
  
// Interface representing functionalities 
// of Trie Data Structure
class interface {
public:
    interface() {}
    virtual ~interface() {}
    // Pure virtual functions showing all 
    // the functions of my Trie class
  
    // To convert character to integer like hashing
    virtual int i2c(char) = 0;
  
    // Inserts word to Trie
    virtual void insertWord(string&) = 0;
  
    // Deletes word if present
    virtual bool deleteWord(string&) = 0;
  
    // To search a word in Trie
    virtual bool searchWord(string&) = 0;
  
    // Checks whether there is any children present
    // for any node
    virtual bool isEmptyNode(shared_ptr) 
                                          const = 0;
};
  
class Trie : public interface {
      
    // Storing root of the Trie
    shared_ptr root;
    int Total_words;
  
public:
    Trie()
    {
        root = shared_ptr
                              (new TrieNode());
        Total_words = 0;
    }
  
    ~Trie()
    {
        // Need not delete anything 
                // as shared_ptr deallocates 
                // all memory automatically
    }
  
    // To convert characters of string into
    // integer like hashing of character
    int i2c(char c)
    {
        return static_cast(c - 'a');
    }
  
    // Insert word function
    void insertWord(string& trieString)
    {
        shared_ptr current = root;
        for (int i = 0; i < trieString.size(); i++) 
                {
              
            // If word after some prefix is not 
                        // present then creates new node
            if (current->children[i2c(trieString[i])] == 
                          shared_ptr(nullptr)) 
            {
                current->children[i2c(trieString[i])] = 
                     shared_ptr(new TrieNode());
            }
            current = (current->children[i2c(trieString[i])]);
        }
  
        // Now word is added in Trie so at leaf node 
        // for that word isWord=true
        current->isWord = true;
    }
  
    // Searching for word whether it is 
    // present in Trie
    bool searchWord(string& trieString)
    {
        shared_ptr current = root;
  
        for (int i = 0; i < trieString.size(); i++) 
        {
            // If at any point in Trie Node for particular 
            // character is not present means nullptr then 
            // return false
            if (current->children[i2c(trieString[i])] == 
                            shared_ptr(nullptr))
                return false;
            current = current->children[i2c(trieString[i])];
        }
  
        // At the end of the word checking whether this
        // word is really present or not
        if (current->isWord == true)
            return true;
  
        return false;
    }
  
    bool Partdelete(string& trieString, shared_ptr&      
                                                     checkout)
    {
        // Word is not present in the Trie then returns 
        // false and stops further recursion
        if (checkout == nullptr)
            return false;
  
        // At the end of the word if the word is 
        // present in trie then setting isWord to 
        // false either returing false
        if (trieString.size() == 0) {
            if (checkout->isWord == true) {
                checkout->isWord = false;
                return true;
            }
            return false;
        }
  
        // String excluding first character
        string part = trieString.substr(1);
  
        // Recusive call to Partdelete for 
        // rest of the string(part)
        if (Partdelete(part, checkout->
                      children[i2c(trieString[0])])) {
                            
            // Checks whether it is empty node 
            // then delete this node
            if (isEmptyNode(checkout->
                      children[i2c(trieString[0])])) {
                            
                // Resetting memory and making it nullptr
                checkout->children[i2c(trieString[0])].
                                                 reset();
                                                   
                checkout->children[i2c(trieString[0])] = 
                                                  nullptr;
                  
                return true;
            }
            else
                return true;
        }
        else
            return false;
  
        return false;
    }
  
    // For ease of recursion; passing 
    // root to Partdelete
    bool deleteWord(string& trieString)
    {
        if (Partdelete(trieString, root))
            return true;
        return false;
    }
  
    // Checks whether there is no children present
    bool isEmptyNode(shared_ptr check) const
    {
        for (int i = 0; i < ALPHABET_SIZE; i++) {
            if (check->children[i] != nullptr || 
                              check->isWord == true)
                return false;
        }
        return true;
    }
};
  
// Driver code
int main()
{
    // Again using shared_ptr to store Trie
    // you can use auto_ptr here
    shared_ptr myTrie(new Trie());
  
    string word1 = "geeksfor";
    string word2 = "geeksforgeeks";
    string word3 = "nothing";
  
    myTrie->insertWord(word1);
  
    if (myTrie->searchWord(word1))
        cout << word1 << ": Is Present" << endl;
    else
        cout << word1 << ": Not Present" << endl;
  
    if (myTrie->searchWord(word3))
        cout << word3 << ": Is Present" << endl;
    else
        cout << word3 << ": Not Present" << endl;
  
    myTrie->insertWord(word2);
  
    if (myTrie->deleteWord(word2))
        cout << word2 << ": Successfully deleted" << endl;
    else
        cout << word2 << ": Not Present" << endl;
  
    if (myTrie->searchWord(word2))
        cout << word2 << ": Is Present" << endl;
    else
        cout << word2 << ": Not Present" << endl;
  
}
输出:
geeksfor: Is Present
nothing: Not Present
geeksforgeeks: Successfully deleted
geeksforgeeks: Not Present