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

    技术2025-07-16  11

    古人有云:“一杯茶,一包烟,一个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,多一点爱!

    Processed: 0.009, SQL: 9