LC208——Trie(前缀树)

Trie树是一种树数据结构,用于检索字符串数据集中的键。

主要应用有:

1.自动补全
谷歌搜索建议

2.拼写检查
拼写检查
3.IP路由(最长前缀匹配)
最长前缀匹配算法,Internet协议(IP)路由中利用转发表选择路径
4.T9打字预测
打字预测
5.单词游戏
单词游戏

比哈希表的优势在于

一、可高效的完成
1.找到具有同一前缀的全部键值
2.按词典序枚举字符串的数据集
二、
随着哈希表大小增加,冲突也增加,时间复杂度增长到O(n)
Trie树存储多个具有相同前缀的键时使用较小的空间,只需要O(m)的时间复杂度,m为键长
平衡树中查找键值需要O(mlogn)的时间复杂度

Trie的结点结构

1.有根树
2.最多R个指向子节点的链接,每个链接指向数据集中的一个字母
3.布尔字段,以指定节点是对应键的结尾还是只是键前缀
leet在trie树中的表示

class TrieNode {

    // R links to node children
    private TrieNode[] links;

    private final int R = 26;

    private boolean isEnd;

    public TrieNode() {
        links = new TrieNode[R];
    }

    public boolean containsKey(char ch) {
        return links[ch -'a'] != null;
    }
    public TrieNode get(char ch) {
        return links[ch -'a'];
    }
    public void put(char ch, TrieNode node) {
        links[ch -'a'] = node;
    }
    public void setEnd() {
        isEnd = true;
    }
    public boolean isEnd() {
        return isEnd;
    }
}

操作

一、插入键
通过搜索Trie树来插入一个键,从根开始搜索
1.链接存在,沿着链接移动到树的下一个子层,并继续搜索下一个键字符
2.链接不存在,创建一个新的节点,并将它与父节点的链接相连,该链接与当前的键字符匹配

到达最后一个字符,将当前节点标记为结束节点
插入

class Trie {
    private TrieNode root;

    public Trie() {
        root = new TrieNode();
    }

    // Inserts a word into the trie.
    public void insert(String word) {
        TrieNode node = root;
        for (int i = 0; i < word.length(); i++) {
            char currentChar = word.charAt(i);
            if (!node.containsKey(currentChar)) {
                node.put(currentChar, new TrieNode());
            }
            node = node.get(currentChar);
        }
        node.setEnd();
    }
}

二、查找键
从第一个键字符开始,检查当前节点中与键字符对应的链接
1.存在链接,移动到链接后面路径中的下一个节点,继续搜索
2.不存在链接,无键字符,且当前节点标记为isEnd,返回True
否则,还有键剩余,找不到后续路径;没有键剩余,当前节点没有标记为isEnd,两种情况都返回false
查找

class Trie {
    ...

    // search a prefix or whole key in trie and
    // returns the node where search ends
    private TrieNode searchPrefix(String word) {
        TrieNode node = root;
        for (int i = 0; i < word.length(); i++) {
           char curLetter = word.charAt(i);
           if (node.containsKey(curLetter)) {
               node = node.get(curLetter);
           } else {
               return null;
           }
        }
        return node;
    }

    // Returns if the word is in the trie.
    public boolean search(String word) {
       TrieNode node = searchPrefix(word);
       return node != null && node.isEnd();
    }
}

三、查找前缀
从根遍历,知道键没有字符,或者无法继续前进,到达键末尾返回true,否则false
前缀查找

class Trie {
    ...

    // Returns if there is any word in the trie
    // that starts with the given prefix.
    public boolean startsWith(String prefix) {
        TrieNode node = searchPrefix(prefix);
        return node != null;
    }
}

C++简化版本

class TrieNode
{
public:
    TrieNode* next[26];
    bool isend;
    TrieNode(){
        isend = false;
        memset(next,0,sizeof(next));
    }
};

class trie
{
    TrieNode* root;
public:
    trie(){
        root = new TrieNode();
    }

    void insert(string word){
        TrieNode* cur = root;
        for(int i=0;i<word.size();i++){
            cout<<word[i]<<endl;
            if(cur->next[word[i]-'a']==NULL){
                cur->next[word[i]-'a'] = new TrieNode();
            }
            cur=cur->next[word[i]-'a'];
        }
        cur->isend = true;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值