1. 概念

Trie树,又叫字典树前缀树(Prefix Tree)单词查找树键树

上图是一棵Trie树,表示了关键字集合{“a”, “to”, “tea”, “ted”, “ten”, “i”, “in”, “inn”} 。

Trie树的基本性质:

  1. 根节点不包含字符,除根节点外的每一个子节点都包含一个字符。
  2. 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
  3. 每个节点的所有子节点包含的字符互不相同。

2. Trie树的优缺点

Trie树的核心思想是空间换时间,利用字符串的公共前缀来减少无谓的字符串比较以达到提高查询效率的目的。

优点

  1. 插入和查询的效率很高,都为O(m),其中m是待插入/查询的字符串的长度。
  2. 不同于hash,Trie树中不同的关键字不会产生冲突。
  3. Trie树可以对关键字按字典序排序。

3. Trie树的应用

  1. 字符串检索
  2. 词频统计
    • 相比hash, trie树可以压缩空间
  3. 字符串排序
  4. 前缀匹配

4. Trie树的实现

from collections import defaultdict
class TrieNode(object):
    def __init__(self):
        self.children = defaultdict(TrieNode)
        self.is_word = False
        # self.word = None

class Trie(object):

    def __init__(self):
        self.root = TrieNode()
        

    def insert(self, word):
        current = self.root
        for letter in word:
            current = current.children[letter]
        current.is_word = True
        # current.word = word
        

    def search(self, word):
        current = self.root
        for letter in word:
            current = current.children.get(letter)
            if not current:
                return False
        return current.is_word
        

    def startsWith(self, prefix):
        current = self.root
        for letter in prefix:
            current = current.children.get(letter)
            if not current:
                return False
        return True
class TrieNode {
    public char val;
    public boolean isWord; 
    public TrieNode[] children = new TrieNode[26];
    public TrieNode() {}
    public TrieNode(char c){
        val = c;
    }
}

public class Trie {
    private TrieNode root;
    public Trie() {
        root = new TrieNode();
        root.val = ' ';
    }

    public void insert(String word) {
        TrieNode current = root;
        for(int i = 0; i < word.length(); i++){
            char c = word.charAt(i);
            if(current.children[c - 'a'] == null){
                current.children[c - 'a'] = new TrieNode(c);
            }
            current = current.children[c - 'a'];
        }
        current.isWord = true;
    }

    public boolean search(String word) {
        TrieNode current = root; 
        for(int i = 0; i < word.length(); i++){
            char c = word.charAt(i);
            if(current.children[c - 'a'] == null) return false;
            current = current.children[c - 'a'];
        }
        return current.isWord;
    }

    public boolean startsWith(String prefix) {
        TrieNode current = root; 
        for(int i = 0; i < prefix.length(); i++){
            char c = prefix.charAt(i);
            if(current.children[c - 'a'] == null) return false;
            current = current.children[c - 'a'];
        }
        return true;
    }
}
class TrieNode{
public:
    char val;
    int weight;
    TrieNode *children[26];
    TrieNode() {}
    TrieNode(char c){
        val = c;
    }
    ~TrieNode();
};

class Trie {
private:
    TrieNode* root;
public:
    Trie() { root = new TrieNode(' '); }

    void insert(string word, int weight) {
        TrieNode* current = root;
        for(int i = 0; i < word.length(); i++){
            char c = word[i];
            if(!current->children[c - 'a']){
                current->children[c - 'a'] = new TrieNode(c);
            }
            current = current->children[c - 'a'];
        }
        current->weight = weight;
    }

    TrieNode* startsWith(string prefix) {
        TrieNode* current = root;
        for(int i = 0; i < prefix.length(); i++){
            char c = prefix[i];
            if(!current->children[c - 'a']) return nullptr;
            current = current->children[c - 'a'];
        }
        return current;
    }
}

ShengYg

Step after step the ladder is ascended.


Tags • tree