迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > 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

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

本文地址:

相关文章

如何在 Java 中延迟几秒钟的时间

发布时间:2023/12/17 浏览次数:217 分类:Java

本篇文章主要介绍如何在 Java 中制造程序延迟。本教程介绍了如何在 Java 中制造程序延时,并列举了一些示例代码来了解它。

如何在 Java 中把 Hashmap 转换为 JSON 对象

发布时间:2023/12/17 浏览次数:187 分类:Java

它描述了允许我们将哈希图转换为简单的 JSON 对象的方法。本文介绍了在 Java 中把 Hashmap 转换为 JSON 对象的方法。我们将看到关于创建一个 hashmap,然后将其转换为 JSON 对象的详细例子。

如何在 Java 中按值排序 Map

发布时间:2023/12/17 浏览次数:171 分类:Java

本文介绍了如何在 Java 中按值对 Map 进行排序。本教程介绍了如何在 Java 中按值对 Map 进行排序,并列出了一些示例代码来理解它。

如何在 Java 中打印 HashMap

发布时间:2023/12/17 浏览次数:192 分类:Java

本帖介绍了如何在 Java 中打印 HashMap。本教程介绍了如何在 Java 中打印 HashMap 元素,还列举了一些示例代码来理解这个主题。

在 Java 中更新 Hashmap 的值

发布时间:2023/12/17 浏览次数:146 分类:Java

本文介绍了如何在 Java 中更新 HashMap 中的一个值。本文介绍了如何在 Java 中使用 HashMap 类中包含的两个方法-put() 和 replace() 更新 HashMap 中的值。

Java 中的 hashmap 和 map 之间的区别

发布时间:2023/12/17 浏览次数:79 分类:Java

本文介绍了 Java 中的 hashmap 和 map 接口之间的区别。本教程介绍了 Java 中 Map 和 HashMap 之间的主要区别。在 Java 中,Map 是用于以键值对存储数据的接口,

在 Java 中获取用户主目录

发布时间:2023/12/17 浏览次数:218 分类:Java

这篇文章向你展示了如何在 Java 中获取用户主目录。本教程介绍了如何在 Java 中获取用户主目录,并列出了一些示例代码以指导你完成该主题。

Java 中 size 和 length 的区别

发布时间:2023/12/17 浏览次数:179 分类:Java

这篇文章教你如何知道 Java 中大小和长度之间的区别。本教程介绍了 Java 中大小和长度之间的区别。我们还列出了一些示例代码以帮助你理解该主题。

Java 中的互斥锁

发布时间:2023/12/17 浏览次数:111 分类:Java

了解有关 Java 中互斥锁的一切,在计算机科学领域,互斥或互斥被称为并发控制的属性。每台计算机都使用称为线程的最小程序指令序列。有一次,计算机在一个线程上工作。为了更好地理解,

扫一扫阅读全部技术教程

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

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便