Java实现前缀树

前缀树 Trie

  1. Trie,又称前缀树或字典树,用于判断字符串是否存在或者是否具有某种字符串前缀。
    在这里插入图片描述

  2. 一个保存了8个键的trie结构,“A”, “to”, “tea”, “ted”, “ten”, “i”, “in”, and “inn”.

  3. 在计算机科学中,trie,又称前缀树字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。(来源:wiki)

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

    优点
    插入和查询的效率很高,都为O(m)O(m),其中 mm 是待插入/查询的字符串的长度。

    关于查询,会有人说 hash 表时间复杂度是O(1)O(1)不是更快?但是,哈希搜索的效率通常取决于 hash 函数的好坏,若一个坏的 hash 函数导致很多的冲突,效率并不一定比Trie树高。
    Trie树中不同的关键字不会产生冲突。

    Trie树只有在允许一个关键字关联多个值的情况下才有类似hash碰撞发生。

    Trie树不用求 hash 值,对短字符串有更快的速度。通常,求hash值也是需要遍历字符串的。

    Trie树可以对关键字按字典序排序。

    缺点
    当 hash 函数很好时,Trie树的查找效率会低于哈希搜索。

    空间消耗比较大。


实现 Trie-leetcode (前缀树)

class Trie {

    /** Initialize your data structure here. */
    //build node class
    private class Node{
        Node[] childs=new Node[26];
        boolean isLeaf;
    }
    // initalize root node
    private Node root = new Node();
    public Trie() {
        
    }
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        insert(word,root);
    }
    private void insert(String word,Node node){
        if (node==null) return;
        if (word.length()==0){
            node.isLeaf=true;
            return;
        }
        int index=indexForChar(word.charAt(0));
        if (node.childs[index]==null){
            node.childs[index]=new Node();
        }
        insert(word.substring(1),node.childs[index]);
    }
    
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        return search(word,root);
    }
    private boolean search(String word,Node node){
        if (node==null) return false;
        if (word.length()==0) return node.isLeaf;
        int index=indexForChar(word.charAt(0));
        return search(word.substring(1),node.childs[index]);
    }
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        return startsWith(prefix,root);
    }
    private boolean startsWith(String prefix,Node node){
        if (node==null) return false;
        if (prefix.length()==0) return true;
        int index=indexForChar(prefix.charAt(0));
        if (node.childs[index]==null) return false;
        return startsWith(prefix.substring(1),node.childs[index]);
    }

    // get char index
    private int indexForChar(char c){
        return c-'a';
    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * boolean param_2 = obj.search(word);
 * boolean param_3 = obj.startsWith(prefix);
 */
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前缀树,也称为字典树或Trie树,是一种树形数据结构,用于有效地处理字符串查找问题。每个节点表示一个字符串前缀,节点可以有零个或多个子节点。这提供一份用Java实现前缀树的代码示例: ```java class TrieNode { // 存储子节点 private TrieNode[] children; // 标识是否是一个单词的结束节点 private boolean isEndOfWord; public TrieNode() { children = new TrieNode[26]; isEndOfWord = false; } public void insert(String word) { // 从根节点开始遍历 TrieNode curNode = this; for(char c : word.toCharArray()) { int index = c - 'a'; if(curNode.children[index] == null) { // 如果子节点不存在,则新建一个 curNode.children[index] = new TrieNode(); } // 继续遍历下一个节点 curNode = curNode.children[index]; } // 最后一个节点标识为单词结束节点 curNode.isEndOfWord = true; } public boolean search(String word) { TrieNode curNode = this; for(char c : word.toCharArray()) { int index = c - 'a'; if(curNode.children[index] == null) { // 如果不存在该节点 return false; } curNode = curNode.children[index]; } // 如果最后一个节点标识为单词结束节点,则表示查找到该单词 return curNode.isEndOfWord; } public boolean startsWith(String prefix) { TrieNode curNode = this; for(char c : prefix.toCharArray()) { int index = c - 'a'; if(curNode.children[index] == null) { // 如果不存在该节点 return false; } curNode = curNode.children[index]; } // 如果遍历完前缀,最后一个节点不为null,则表示该前缀存在 return true; } } public class Trie { private TrieNode root; public Trie() { root = new TrieNode(); } public void insert(String word) { root.insert(word); } public boolean search(String word) { return root.search(word); } public boolean startsWith(String prefix) { return root.startsWith(prefix); } } ``` 使用方法: ```java public static void main(String[] args) { Trie trie = new Trie(); trie.insert("apple"); boolean result1 = trie.search("apple"); // 返回 true boolean result2 = trie.search("app"); // 返回 false boolean result3 = trie.startsWith("app"); // 返回 true trie.insert("app"); boolean result4 = trie.search("app"); // 返回 true System.out.println(result1 + " " + result2 + " " + result3 + " " + result4); } ``` 输出结果: ``` true false true true ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值