Java 中的 Trie 数据结构
本文介绍了 Java 中的 Trie 数据结构。
Java 中的 Trie 数据结构
Trie 词是从单词 Retrieval 中提取出来的,它是一种用于存储字符串集合的排序数据结构。 Trie可以定义为指针数量等于每个节点中字符数量的数据结构。
借助单词前缀,Trie 数据结构可用于从字典中搜索单词。 在这种情况下,如果字典中的所有单词都由 26 个英文字母组成,则每个 Trie 节点将有 26 个点。
Trie 数据结构也称为前缀树或数字树,其中节点的位置将决定该节点将连接的键。 我们尝试通过下图来了解 Trie 的工作原理:
上图包含了单词 deal、delft 和 delete 的树结构。
Trie 数据结构的属性
以下是字符串 Trie 集的主要属性:
- 根节点始终为空节点。
- 每个子节点都将按字母顺序排序。
- 由于英文字母的原因,每个节点不能有超过 26 个子节点。
- 每个节点可以存储字母表中的一个字母。
Trie数据结构的应用
让我们看看Trie数据结构的一些主要应用:
- 当需要假设所有字母都是小写时,可以使用 Trie。
- 当我们只能使用 a-z 的字母,没有连字符,没有标点符号等时。
- 当单词的长度有限时。 例如,如果我们正在处理 2x2 的板,则字长不能超过 4,因此可以丢弃这些字。
- 字典中的许多单词具有相同的词干,例如草坪和割草机。 Trie 可以用于这些词形变化的单词。
Trie数据结构的基本操作
Trie 具有三个基本操作:
插入操作
第一个操作是向 Trie 中插入一个节点。 为此,我们需要了解以下几点:
- 输入单词的每个字母都将作为个体插入到 Trie 节点中。
- 字符长度将决定 Trie 的长度。
- 键字符数组将充当子项的索引。
- 如果当前节点有对当前字母的引用,则设置引用该节点的当前节点。 否则,应创建一个新节点。
搜索操作
Trie 的第二个基本操作是搜索节点。 这个操作也和插入类似。
我们只需使用相同的方法搜索节点即可。
删除操作
第三个操作是删除节点。 这也是一个简单的操作。
在开始删除之前我们必须考虑两点:
- 如果搜索时没有找到节点键,则删除操作将停止并退出。
- 如果在搜索 Trie 时找到节点键,则删除操作将删除该键。
Trie数据结构的Java实现
我们来尝试实现Trie数据结构,它只支持小写a-z英文字符。 参见示例:
package jiyik;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Trie_Node {
// 26 characters for a – z
private static final int CHARACTER_SIZE = 26;
private boolean Is_Leaf;
private List<Trie_Node> Trie_Children = null;
// Constructor
Trie_Node(){
Is_Leaf = false;
Trie_Children= new ArrayList<>(Collections.nCopies(CHARACTER_SIZE, null));
}
// function for insertion
public void Insertion(String Node_Key) {
System.out.println("Inserting the key \"" + Node_Key + "\"");
// root node
Trie_Node root_node = this;
// repeat for every character of the key
for (char character: Node_Key.toCharArray()) {
// create a new Trie node if the path does not exist
if (root_node.Trie_Children.get(character - 'a') == null) {
root_node.Trie_Children.set(character - 'a', new Trie_Node());
}
// going to the next node
root_node = root_node.Trie_Children.get(character - 'a');
}
//current node as a leaf
root_node.Is_Leaf = true;
}
// Method for search
public boolean Searching(String Node_Key) {
System.out.print("Searching the key \"" + Node_Key + "\" : ");
Trie_Node Current_Node = this;
// repeat for the character of the key
for (char character: Node_Key.toCharArray()) {
// going to the next node
Current_Node = Current_Node.Trie_Children.get(character - 'a');
// reach out to the end of a path in the Trie if the string is invalid
if (Current_Node == null) {
return false;
}
}
return Current_Node.Is_Leaf;
}
}
public class Example {
public static void main (String[] args) {
// construct a new Trie node
Trie_Node New_Trie = new Trie_Node();
New_Trie.Insertion("delft");
New_Trie.Insertion("delf");
New_Trie.Insertion("del");
System.out.println(New_Trie.Searching("del")); // true
System.out.println(New_Trie.Searching("delf")); // true
System.out.println(New_Trie.Searching("delft")); // true
System.out.println(New_Trie.Searching("jiyik")); // false
New_Trie.Insertion("jiyik");
System.out.println(New_Trie.Searching("del")); // true
System.out.println(New_Trie.Searching("delf")); // true
System.out.println(New_Trie.Searching("delft")); // true
System.out.println(New_Trie.Searching("jiyik")); // true
}
}
上面的代码实现了Trie数据结构的插入和查找操作。 查看输出:
Inserting the key "delft"
Inserting the key "delf"
Inserting the key "del"
Searching the key "del" : true
Searching the key "delf" : true
Searching the key "delft" : true
Searching the key "jiyik" : false
Inserting the key "jiyik"
Searching the key "del" : true
Searching the key "delf" : true
Searching the key "delft" : true
Searching the key "jiyik" : true
现在,Trie 数据结构的空间复杂度为 O(N × M × C)
,其中:
- N - 字符串数量
- M - 字符串的最大长度。
- C - 字母表的大小
因此,在具有上述空间复杂度的Java中,可能会出现存储问题。
我们还可以利用Java中的HashMap来实现Trie来解决存储问题。 让我们尝试使用 HashMap 来实现 Trie:
package jiyik;
import java.util.HashMap;
import java.util.Map;
class Trie_Node{
private boolean Is_Leaf;
private Map<Character, Trie_Node> Trie_Children;
// Constructor
Trie_Node()
{
Is_Leaf = false;
Trie_Children = new HashMap<>();
}
// Insertion
public void Insertion(String Node_Key)
{
System.out.println("Inserting the key \"" + Node_Key + "\"");
// root node
Trie_Node root_node = this;
for (char character: Node_Key.toCharArray()) {
// if the path doesn't exist, create a new node.
root_node.Trie_Children.putIfAbsent(character, new Trie_Node());
// going to the next node
root_node = root_node.Trie_Children.get(character);
}
root_node.Is_Leaf = true;
}
// Searching
public boolean Searching(String Node_key) {
System.out.print("Searching the key \"" + Node_key + "\" : ");
Trie_Node Current_Node = this;
// repeat
for (char character: Node_key.toCharArray()) {
// going to the next node
Current_Node = Current_Node.Trie_Children.get(character);
if (Current_Node == null) {
return false;
}
}
return Current_Node.Is_Leaf;
}
}
public class Example {
public static void main (String[] args) {
// construct a new Trie node
Trie_Node New_Trie = new Trie_Node();
New_Trie.Insertion("delft");
New_Trie.Insertion("delf");
New_Trie.Insertion("del");
System.out.println(New_Trie.Searching("del")); // true
System.out.println(New_Trie.Searching("delf")); // true
System.out.println(New_Trie.Searching("delft")); // true
System.out.println(New_Trie.Searching("jiyik")); // false
New_Trie.Insertion("jiyik");
System.out.println(New_Trie.Searching("del")); // true
System.out.println(New_Trie.Searching("delf")); // true
System.out.println(New_Trie.Searching("delft")); // true
System.out.println(New_Trie.Searching("jiyik")); // true
}
}
该代码执行相同的工作,但以更节省内存的方式进行。 查看 Java 中 Trie 的输出:
Inserting the key "delft"
Inserting the key "delf"
Inserting the key "del"
Searching the key "del" : true
Searching the key "delf" : true
Searching the key "delft" : true
Searching the key "jiyik" : false
Inserting the key "jiyik"
Searching the key "del" : true
Searching the key "delf" : true
Searching the key "delft" : true
Searching the key "jiyik" : true
相关文章
JAVA_OPTS 环境变量
发布时间:2023/08/05 浏览次数:199 分类:Java
-
JAVA_OPTS 是一个环境变量,用于将自定义设置传递给 Java 虚拟机。 本文介绍了 JAVA_OPTS 的使用。JAVA_OPTS 环境变量 JAVA_OPTS 是一个标准环境变量,用于设置 Java 虚拟机的自定义设置。
在Ubuntu中设置JAVA_HOME环境路径
发布时间:2023/08/05 浏览次数:154 分类:Java
-
本文将介绍如何在Ubuntu中设置Java环境路径。 Ubuntu 将 openjdk6 安装到 /usr/lib/jvm/java-6-openjdk 路径。
在 Ubuntu 中使用 OpenJDK 安装 Java
发布时间:2023/08/05 浏览次数:179 分类:Java
-
在本文中,我们将学习如何在 Ubuntu 20.04 中安装 Java。 它还说明了如何安装默认 Java、特定 Java 版本以及设置环境变量。在 Ubuntu 中使用 OpenJDK 安装 Java 在本文中,我们将使用 OpenJDK 安装 Java。
使用 Brew 安装 Java
发布时间:2023/08/05 浏览次数:66 分类:Java
-
本文将展示如何使用 BREW 安装 Java。什么是 BREW 和 HOMEBREW? 使用 BREW 安装 Java 需要什么? 答案就在这篇文章中,所以让我们立即开始吧。
Java 中的尖括号
发布时间:2023/08/05 浏览次数:167 分类:Java
-
本文介绍什么是 Java 中的尖括号 (<>) 以及如何使用它。Java 中的尖括号 (<>) 让我们举个例子; 我们有一个名为 Delftstack 的类,
在 Java 中将数字转换为单词
发布时间:2023/08/05 浏览次数:73 分类:Java
-
本文介绍如何在 Java 中将数字转换为单词。有时我们需要将数字转换为文字; 例如,123 应转换为一百二十三。 这可以在 Java 中通过小数或大数来实现。 在 Java 中将四位数转换为单词
默认 Java 密钥库密码
发布时间:2023/08/05 浏览次数:125 分类:Java
-
本文将引导您更改 Java 密钥库密码。 但在继续之前,我们需要对密钥库有一个基本的了解,所以让我们看一下。Java 中的密钥库
Java 中的 Cacerts 与 Keystore
发布时间:2023/08/05 浏览次数:152 分类:Java
-
本文对 cacerts 和 KeyStore 进行了比较并重点介绍了差异。Java 中的 cacerts 与 KeyStore cacerts 是用于验证对等方的 TrustStore,而 KeyStore 用于验证您自己的身份。