构建前缀树(字典树)---Java实现

古人有云:“一杯茶,一包烟,一个bug调一天。”
今天我是切身体会到代码出问题,还是在逻辑语法都没问题的情况下的心塞。后来才发现是题目提供的方法名我少写了一个"s",就是下面startswith的方法名中的s。就这一个小点,搞了3个多小时!!!!
废话不多说,我们来看看什么是前缀树:又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
搜索字典项目的方法为:
(1) 从根结点开始一次搜索;
(2) 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;
(3) 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。
(4) 迭代过程……
(5) 在某个结点处,关键词的所有字母已被取出,则读取附在该结点上的信息,即完成查找。
其他操作类似处理。
具体的应用:串的快速检索、“串”排序、最长公共前缀
在这里插入图片描述
介绍完定义之后,我们来从力扣上一道题入手来编写Trie树。
leetcode208. 实现 Trie (前缀树)
链接:https://leetcode-cn.com/problems/implement-trie-prefix-tree/
难度:中等
题目:
实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。
示例:
Trie trie = new Trie();
trie.insert(“apple”);
trie.search(“apple”); // 返回 true
trie.search(“app”); // 返回 false
trie.startsWith(“app”); // 返回 true
trie.insert(“app”);
trie.search(“app”); // 返回 true
方法一:
第一步我们先要构建树的结点:由题目要求可以知道

class TrieNode {
    boolean isleaf;
    Map<Character,TrieNode> next;//用来存,下一个结点的信息,K是存储字符,Value存储结点
    public TrieNode(){
        next=new HashMap<Character,TrieNode>();
    }

}

第二步构建Trie树,并实现search、insert、startswith方法

class Trie{
    private TrieNode root;//定义根节点
    public Trie(){
        root = new TrieNode();
    }
    //方法:插入方法
     public void insert(String word){
        if(word == null || word.length() == 0){
            return ;
        }
        TrieNode node = root;
        int len=word.length();
        for(int i=0;i<len;i++){
            Character c = word.charAt(i);
            TrieNode tempNode = node.next.get(c);
            if(tempNode == null){
               tempNode =  new TrieNode();
                node.next.put(c,tempNode);
            }
            node=tempNode;
        }
        node.isleaf = true;
     }

     //search方法
     public boolean search(String word){
        if(word == null || word.length() == 0){
            return false;
        }
        TrieNode node =root;
        int len=word.length();
        for(int i=0;i<len;i++){
            Character c = word.charAt(i);
            TrieNode tempNode = node.next.get(c);
            if(tempNode == null){
                return false;
            }
            node = tempNode;
        }
        return node.isleaf;
     }
    //返回trie中是否有给定前缀开头的单词
     public boolean startsWith(String prefix){
        if(prefix == null || prefix.length() == 0) return false;
        TrieNode node = root;
        int len=prefix.length();
        for(int i=0;i<len;i++){
            TrieNode tempNode = node.next.get(prefix.charAt(i));
            if(tempNode == null){
                return false;
            }
            node=tempNode;
        }
        return true;//不需要判断是否是叶结点

     }
}

方法二:
构建结点:是用数组,其实在结点构造这块,定义的方法是模拟map

class TrieNode{
    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:

public class Trie {
    private TrieNode root;
    public Trie(){
        root = new TrieNode();
    }
    //inset
    public void insert(String word){
        if(word == null || word.length() == 0) return ;
        TrieNode node =root;
        for(int i=0;i<word.length();i++){
            char c = word.charAt(i);
            if(!node.containsKey(c)){
                node.put(c,new TrieNode());
            }
            node = node.get(c);//node指向下一个结点
        }
        node.setEnd();
    }
    //searchPrefix
    public TrieNode searchPrefix(String word){
        if(word == null || word.length() == 0) return false;
        TrieNode node=root;
        for(int i=0;i<word.length();i++){
            char c = word.charAt(i);
            if(node.containsKey(c)){
                node=node.get(c);
            }else{
                return null;
            }
        }
        return node;
    }

    //search
    public boolean search(String word){
        TrieNode node = searchPrefix(word);
        return node != null && node.isEnd();
    }

}

希望世界少一点bug,多一点爱!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值