Trie 树(前缀树)

一、Trie 树是我一直想看却一直拖着没看的数据结构。主要应用的思想是通过构建树结构,使得前缀相同的字符串可共享前缀序列,一旦构建好树结构后,便可实现快速检索。

适用场景:1)找到所有前缀相同的字符串    2)以字典序枚举数据集中的每个字符串。

哈希表在上述两种场景下会有大量的哈希碰撞(hash collisions)且搜索的时间复杂度很高(最差情形下为 O(n),n为插入的键值数)。故相较于哈希表,Trie可通过存储相同前缀的字符串节省更多的空间,故搜索的时间复杂度仅为O(m), m为键长(即字符串长度)

二、主要的应用有:构建字典(查询某个单词是否在字典中)、自动纠正语法错误、自动补齐单词、IP地址路由选择等。

1)根节点的特点

1. Trie为有根树,根节点为空,不表示任何字符

2. 每个节点最多有R个孩子(若字符串中每个字符取值为‘a’~‘z’,则R=26),第i个孩子表示字母表中的第i个字符

2)插入元素

依次遍历字符串中的每个元素,若该元素存在,继续遍历下一元素;否则,插入一新的节点。

3)查找某字符串是否存在

与2)类似,依次遍历字符串中的每个元素,若该元素存在,继续遍历下一元素;否则,返回false。

例题:LeetCode 208. Implement Trie

代码如下:

class TrieNode{
public:
    char var;   //该节点对应的字符
    bool isword;        //标记从根节点到该节点是否表示一个单词或另一单词的前缀
    TrieNode* child[26];    //子节点用一个数组表示,实现简单但耗内存
    // Initialize the data structure
    TrieNode()
    {
        var = 0;
        isword = false;
        memset(child, 0, sizeof(child));
    }
    TrieNode(char c)
    {
        var = c;
        isword = false;
        memset(child, 0, sizeof(child));
    }
    
};

class Trie {
public:
    /** Initialize your data structure here. */
    Trie() {
        root = new TrieNode();
    }
    
    /** Inserts a word into the trie. */
    void insert(string word) {      
        if(word.length()<=0) return;
        TrieNode *pNode = root;
        for(int i=0; i<word.length(); ++i)
        {
            char c = word[i];
            if(pNode->child[c-'a'] == 0)
            {
                TrieNode *pNew = new TrieNode(c);
                pNode->child[c-'a'] = pNew;
            }
            pNode = pNode->child[c-'a'];
        }
        pNode->isword = true;
    }
    
    /** Returns if the word is in the trie. */
    bool search(string word) {
        TrieNode *pNode = root;
        if(word.length()<=0) return true;
        for(int i=0; i<word.length(); ++i)
        {
            char c = word[i];
            pNode = pNode->child[c-'a'];
            if(pNode==NULL) return false;
        }
        return pNode->isword;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {      
        if(prefix.length()<=0) return true;
        TrieNode *pNode = root;
        for(int i=0; i<prefix.length(); ++i)
        {
            char c = prefix[i];
            pNode = pNode->child[c-'a'];
            if(pNode==NULL) return false;
        }
        return true;
    }
private:
    TrieNode *root;
};

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * bool param_2 = obj.search(word);
 * bool param_3 = obj.startsWith(prefix);
 */

参考链接: https://leetcode.com/problems/implement-trie-prefix-tree/solution/

                  https://blog.csdn.net/sunao2002002/article/details/46661761

猜你喜欢

转载自blog.csdn.net/qq_24153697/article/details/79820989