10.4 Trie字典树前缀查询

10.4 Trie字典树前缀查询

Tip:本博客内容是通过学习慕课网bobo老师视频做的笔记总结,不用于任何商业用途,只用于帮助更多技术爱好者。

(1) Trie字典树的Java语言实现案例

// 在Trie树中查找是否存在某个prefix前缀的单词,即实现前缀树
public boolean isPrefix(String prefix)
package com.wwl.trie;



import java.util.TreeMap;



/**

 * Trie树性能高于BST(二分搜索树)

 * Trie时间复杂度:O(w) 与单词长度有关

 * BST时间复杂度:O(logn) 与存储的数据条目有关

 */

public class Trie {



    private class Node {

        private boolean isWord;

        private TreeMap next;



        public Node(boolean isWord) {

            this.isWord = isWord;

            next = new TreeMap<>();

        }



        public Node() {

            this(false);

        }

    }



    // Trie树根节点定义

    private Node root;

    // Trie树存储单词数

    private int size;



    public Trie() {

        root = new Node();

        this.size = 0;

    }



    // 获取Trie树存储的单词数

    public int getSize() {

        return size;

    }



    // 向Trie树种添加一个新的词汇

    public void add(String word) {

        // 字符串判空操作

        if (word == null) {

            return;

        }

        // 定义当前节点

        Node cur = root;

        // 对新加入Trie树的词汇进行识别

        // 第一:如果新加入的字符不存在,则在当前node节点创建一个新的节点树;

        // 第二:如果新加入的字符存在,则找到存在的字符节点,然后赋值给当前节点,继续下一步识别。

        for (int i = 0; i < word.length(); i++) {

            char c = word.charAt(i);

            if (cur.next.get(c) == null) {

                cur.next.put(c, new Node());

            }

            cur = cur.next.get(c);

        }



        // 第一:如果当前加入的单词不存在,则把isWord标志改成true,表示加入的单词最后一个字符表示单词结尾;

        // 第二:如果当前假如的字符存在,则不进行逻辑处理。

        if (!cur.isWord) {

            cur.isWord = true;

            size++;

        }

    }



    // 判断Trie树中是否存在某个单词

    public boolean contains(String word) {

        if (word == null) {

            return false;

        }



        // 定义当前节点

        Node cur = root;

        // 第一:如果新加入的字符不存在,则返回false;

        for (int i = 0; i < word.length(); i++) {

            char c = word.charAt(i);

            if (cur.next.get(c) == null) {

                return false;

            }

            cur = cur.next.get(c);

        }

        // 第二:如果新加入的单词的所有字符都存在,则根据当前node节点的isWord字段判断此单词是否存在。

        return cur.isWord;

    }



    // 在Trie树中查找是否存在某个prefix前缀的单词,即实现前缀树

    public boolean isPrefix(String prefix) {

        if (prefix == null) {

            return false;

        }

 

        // 定义当前节点

        Node cur = root;

        // 第一:如果新加入的字符不存在,则返回false;

        for (int i = 0; i < prefix.length(); i++) {

            char c = prefix.charAt(i);

            if (cur.next.get(c) == null) {

                return false;

            }

            cur = cur.next.get(c);

        }

        // 第二:如果新加入的单词的所有字符都存在,则表示Trie树中能查找到此prefix前缀。

        return true;

    }

}

 

(2) Trie字典树的Java测试代码

package com.wwl.trie;



public class TrieIsPrefixTest {



    public static void main(String[] args) {

        Trie trie = new Trie();

        trie.add("hello");

        trie.add("word");

        trie.add("dog");

        trie.add("cat");

        trie.add("beer");

        trie.add("honey");

        trie.add("co-worker");

        trie.add("handsome");



        boolean isPrefix = trie.isPrefix("co");

        System.out.println("查找的前缀prefix是否存在:" + isPrefix);



        isPrefix = trie.contains("co-worker");

        System.out.println("查找的前缀prefix是否存在:" + isPrefix);



        isPrefix = trie.contains("some");

        System.out.println("查找的前缀prefix是否存在:" + isPrefix);



        isPrefix = trie.contains("handsome");

        System.out.println("查找的前缀prefix是否存在:" + isPrefix);

    }

}

程序运行结果如下:

查找的前缀prefix是否存在:true

查找的前缀prefix是否存在:true

查找的前缀prefix是否存在:false

查找的前缀prefix是否存在:true

 

(3) Leetcode实现Trie(前缀树)

https://leetcode-cn.com/problemset/all/?search=Trie%E5%89%8D%E7%BC%80%E6%A0%91

class Trie {

    private class Node {

        private boolean isWord;

        private TreeMap next;

        public Node(boolean isWord) {

            this.isWord = isWord;

            next = new TreeMap<>();

        }

        public Node() {

            this(false);

        }

    }

    // Trie树根节点定义

    private Node root;

    // Trie树存储单词数

    private int size;

    /** Initialize your data structure here. */

    public Trie() {

        root = new Node();

        this.size = 0;

    }

    

    /** Inserts a word into the trie. */

    public void insert(String word) {

        // 字符串判空操作

        if (word == null) {

            return;

        }

        // 定义当前节点

        Node cur = root;

        // 对新加入Trie树的词汇进行识别

        // 第一:如果新加入的字符不存在,则在当前node节点创建一个新的节点树;

        // 第二:如果新加入的字符存在,则找到存在的字符节点,然后赋值给当前节点,继续下一步识别。

        for (int i = 0; i < word.length(); i++) {

            char c = word.charAt(i);

            if (cur.next.get(c) == null) {

                cur.next.put(c, new Node());

            }

            cur = cur.next.get(c);

        }

        // 第一:如果当前加入的单词不存在,则把isWord标志改成true,表示加入的单词最后一个字符表示单词结尾;

        // 第二:如果当前假如的字符存在,则不进行逻辑处理。

        if (!cur.isWord) {

            cur.isWord = true;

            size++;

        }

    }

    

    /** Returns if the word is in the trie. */

    public boolean search(String word) {

        if (word == null) {

            return false;

        }

        // 定义当前节点

        Node cur = root;

        // 第一:如果新加入的字符不存在,则返回false;

        for (int i = 0; i < word.length(); i++) {

            char c = word.charAt(i);

            if (cur.next.get(c) == null) {

                return false;

            }

            cur = cur.next.get(c);

        }

        // 第二:如果新加入的单词的所有字符都存在,则根据当前node节点的isWord字段判断此单词是否存在。

        return cur.isWord;

    }

    

    /** Returns if there is any word in the trie that starts with the given prefix. */

    public boolean startsWith(String prefix) {

        if (prefix == null) {

            return false;

        }

        // 定义当前节点

        Node cur = root;

        // 第一:如果新加入的字符不存在,则返回false;

        for (int i = 0; i < prefix.length(); i++) {

            char c = prefix.charAt(i);

            if (cur.next.get(c) == null) {

                return false;

            }

            cur = cur.next.get(c);

        }

        // 第二:如果新加入的单词的所有字符都存在,则表示Trie树中能查找到此prefix前缀。

        return true;

    }

}

/**

 * 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);

 */

如果感兴趣的童鞋,可以观看我下一篇博客:10.5 Trie字典树和简单模式匹配

你可能感兴趣的:(数据结构)