Trie树 字典树 前缀树

字典树
通过共享字符串的公共前缀来达到节省空间的目的。
比如 “abc” 和 “ab” 和 “d”,构建的字典树如下表示,红色表示一个串的结束。

查找时间复杂度:
如果敏感词的长度为 m(比如26个字母,m就是26) ,每个敏感词的查找时间复杂度为O(m),
字符串的长度为 n ,我们就需要遍历 n 次(针对字符串的每个字符),针对每个字符进行查找,因此查找的整个过程的时间复杂度是 O(m*n)

构建的时间复杂度不用考虑,因为Trie树在一开始就会构建了,构建一次后就可以无数次查询使用。

Trie树 字典树 前缀树_第1张图片




比如我们做一个26个字母的字典树
每个节点下都有26种可能的分支。
因此定义每个节点的结构TrieNode如下:

#include 
#include 
#include 
#include 
#include 

using namespace std;


struct TrieNode
{
     
    bool isEnd;             // 该节点是否是一个串的结束
    TrieNode * next[26];    // 字母映射表,下一个节点的所有可能性。每个节点下main都可能有26个可能的节点
};


class Trie {
     
    private:
        bool isEnd;
        Trie * next[26];

    public:
        Trie() {
     
            isEnd = false;
            memset(next , 0 , sizeof(next));
        }
        
        ~Trie()
        {
     
            Trie * node = this;
            for(int i = 0; i < 26;++i)
            {
     
                if(node->next[i] == NULL)
                {
     
                    continue;
                }
                delete node->next[i];
            }
        }
        
        void insert(string word) {
     
            Trie * node = this;

            for(int i = 0; i < word.length();++i)
            {
     
                if(node->next[word[i]-'a'] == NULL)
                {
     
                    node->next[word[i]-'a'] = new Trie();
                } 
                node = node->next[word[i]-'a'];
            }
            node->isEnd = true;
        }
        
        bool search(string word) {
     
            Trie * node = this;
            for(int i = 0; i < word.length();++i)
            {
     
                node = node->next[word[i]-'a'];
                if(node == NULL)
                {
     
                    return false;
                }   
            }
            
            return node->isEnd;
        }
        
        bool startsWith(string prefix) {
     
            Trie * node = this;
            for(int i = 0; i < prefix.length();++i)
            {
     
                node = node->next[prefix[i]-'a'];
            }
            if(node == NULL)
            {
     
                return false;
            }
        }
};

int main()
{
     
    // 内存泄漏检测 mtrace  编译的时候加上-g
    mtrace();

    Trie * root = new Trie();
    root->insert("apple");
    cout << root->search("apple") << endl;
    cout << root->search("app") << endl;
    
    delete root;
    muntrace();

        return 0;
}

通过 mtrace顺便检测是否有内存泄漏,结果显示没有,因为析构函数中对new出来的节点进行了释放。
Trie树 字典树 前缀树_第2张图片

你可能感兴趣的:(LeetCode,数据结构和算法,数据结构和算法,字典树,Trie)