迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > Java >

Java 中的 Trie 数据结构

作者:迹忆客 最近更新:2023/08/05 浏览次数:

本文介绍了 Java 中的 Trie 数据结构。


Java 中的 Trie 数据结构

Trie 词是从单词 Retrieval 中提取出来的,它是一种用于存储字符串集合的排序数据结构。 Trie可以定义为指针数量等于每个节点中字符数量的数据结构。

借助单词前缀,Trie 数据结构可用于从字典中搜索单词。 在这种情况下,如果字典中的所有单词都由 26 个英文字母组成,则每个 Trie 节点将有 26 个点。

Trie 数据结构也称为前缀树或数字树,其中节点的位置将决定该节点将连接的键。 我们尝试通过下图来了解 Trie 的工作原理:

Trie 数据结构 Java

上图包含了单词 deal、delft 和 delete 的树结构。

Trie 数据结构的属性

以下是字符串 Trie 集的主要属性:

  1. 根节点始终为空节点。
  2. 每个子节点都将按字母顺序排序。
  3. 由于英文字母的原因,每个节点不能有超过 26 个子节点。
  4. 每个节点可以存储字母表中的一个字母。

Trie数据结构的应用

让我们看看Trie数据结构的一些主要应用:

  1. 当需要假设所有字母都是小写时,可以使用 Trie。
  2. 当我们只能使用 a-z 的字母,没有连字符,没有标点符号等时。
  3. 当单词的长度有限时。 例如,如果我们正在处理 2x2 的板,则字长不能超过 4,因此可以丢弃这些字。
  4. 字典中的许多单词具有相同的词干,例如草坪和割草机。 Trie 可以用于这些词形变化的单词。

Trie数据结构的基本操作

Trie 具有三个基本操作:

插入操作

第一个操作是向 Trie 中插入一个节点。 为此,我们需要了解以下几点:

  1. 输入单词的每个字母都将作为个体插入到 Trie 节点中。
  2. 字符长度将决定 Trie 的长度。
  3. 键字符数组将充当子项的索引。
  4. 如果当前节点有对当前字母的引用,则设置引用该节点的当前节点。 否则,应创建一个新节点。

搜索操作

Trie 的第二个基本操作是搜索节点。 这个操作也和插入类似。

我们只需使用相同的方法搜索节点即可。

删除操作

第三个操作是删除节点。 这也是一个简单的操作。

在开始删除之前我们必须考虑两点:

  1. 如果搜索时没有找到节点键,则删除操作将停止并退出。
  2. 如果在搜索 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 环境变量

下一篇:没有了

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

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 浏览次数:126 分类:Java

在本文中,我们将讨论 Java 中的泛型。 此外,我们将使用说明泛型的示例来讨论该主题,并逐部分解释这些代码。Java 中泛型如何确保类型

在 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 用于验证您自己的身份。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便