简体   繁体   English

“简单”Trie实施

[英]“Simple” Trie Implementation

I need to implement a Trie (in Java) for a college project. 我需要为大学项目实现Trie (用Java)。 The Trie should be able to add and remove Strings (for phase 1). Trie应该能够添加和删除字符串(适用于阶段1)。

I have spent several hours each day (for the last few days) trying to figure out how to do this and FAILED miserably each time. 我每天花费几个小时(最近几天)试图弄清楚如何做到这一点并且每次都惨不忍睹。

I require some help, the examples on the internet and my textbook (Data Structures and Algorithms in Java By Adam Drozdek) are not helping. 我需要一些帮助,互联网上的例子和我的教科书(Java中的数据结构和算法,Adam Drozdek)没有帮助。

Information 信息

  1. Node classes I am working with: 我正在使用的节点类:

     class Node { public boolean isLeaf; } class internalNode extends Node { public String letters; //letter[0] = '$' always. //See image -> if letter[1] = 'A' then children[1] refers to child node "AMMO" //See image -> if letter[2] = 'B' then children[2] refers to internal node "#EU" public TrieNode[] children = new TrieNode[2]; public TrieInternalNode(char ch) { letters = "#" + String.valueOf(ch);//letter[0] = '$' always. isLeaf = false; } } class leafNode extends Node { public String word; public TrieLeafNode(String word) { this.word = new String(word); isLeaf = true; } } 
  2. And here is the pseudo code for insert that I need to follow: (warning it is very vague) 这里是我需要遵循的插入伪代码:(警告它很模糊)

     trieInsert(String K) { i = 0; p = the root; while (not inserted) { if the end of word k is reached set the end-of-word marker in p to true; else if (p.ptrs[K[i]] == 0) create a leaf containing K and put its address in p.ptrs[K[i]]; else if reference p.ptrs[K[i]] refers to a leaf { K_L = key in leaf p.ptrs[K[i]] do { create a nonleaf and put its address in p.ptrs[K[i]]; p = the new nonleaf; } while (K[i] == K_L[i++]); } create a leaf containing K and put its address in p.ptrs[K[--i]]; if the end of word k is reached set the end-of-word marker in p to true; else create a leaf containing K_L and put its address in p.ptrs[K_L[i]]; else p = p.ptrs[K[i++]]; } } 
  3. I need to implement the following methods. 我需要实现以下方法。

     public boolean add(String word){...}//adds word to trie structure should return true if successful and false otherwise public boolean remove(String word){...}//removes word from trie structure should return true if successful and false otherwise 
  4. I cant find pseudo code for remove, but if insert does not work delete wont help me. 我找不到删除伪代码,但如果插入不起作用删除不会帮助我。

  5. Here is a image of how the Trie that I need to implement should look like. 这是我需要实现的Trie应该是什么样子的图像。

在此输入图像描述

  1. I am aware that the Trie will still be inefficient if implemented like this, but at the moment I need not worry about this. 我知道如果像这样实现,Trie仍然效率低下,但目前我不用担心这个问题。

  2. The book provides an implementation that is similar to what I need to do but doesn't use the end of word char ('$') and only stores the words without their prefixes in the child nodes http://mathcs.duq.edu/drozdek/DSinJava/SpellCheck.java 本书提供了一个类似于我需要做的实现,但没有使用单词char('$')的结尾,只存储没有前缀的单词在子节点http://mathcs.duq.edu/drozdek/DSinJava/SpellCheck.java

Constraints 约束

  1. I need to implement the trie in JAVA. 我需要在JAVA中实现trie。
  2. I may not import or use any of Java's built-in data structures. 我可能不会导入或使用任何Java的内置数据结构。 (ie. no Map, HashMap, ArrayList etc) (即没有Map,HashMap,ArrayList等)
  3. I may use Arrays, Java primitive Types and Java Strings. 我可以使用Arrays,Java原始类型和Java字符串。
  4. The Trie must use a $ (dollar) symbol to indicate a end-of-word. Trie必须使用$ (美元)符号来表示单词结尾。 (see the image below ) (见下图)

在此输入图像描述

  1. I may asume that now word containing the $ symbol will be inserted. 我可以假设现在插入包含$符号的单词。
  2. I need to implement the Trie it in the same style as the book does. 我需要以与本书相同的风格实现Trie。
  3. Case of words doesn't matter ie. 单词的情况无关紧要即。 all words will be considered to be lowercase 所有单词都将被视为小写
  4. The Trie should only store the end-of-word character and the characters applicable to a word and not the entire alphabet(like some implementations). Trie应该只存储单词结尾字符和适用于单词而不是整个字母表的字符(如某些实现)。

I do not expect anyone to do the implementation for me(unless they have one lying around :P) I just really need help. 我不希望有人为我执行(除非他们有一个人躺着:P)我真的需要帮助。

First of all, I don't think you should make leaf nodes and internal nodes separate classes. 首先,我认为你不应该让叶子节点和内部节点分开类。 I recommend making a universal node class with an isLeaf() method. 我建议使用isLeaf()方法创建通用节点类。 This method would return true if a node has no children. 如果节点没有子节点,则此方法将返回true。

Here is some higher-level pseudocode for the functions you need to implement. 以下是您需要实现的功能的更高级伪代码。 For simplicity, I assume the existence of a method called getIndex() which returns the index corresponding to a character. 为简单起见,我假设存在一个名为getIndex()的方法,该方法返回与字符对应的索引。

Insert(String str)
    Node current = null
    for each character in str
        int index = getIndex(character)
        if current.children[index] has not been initialized
            initialize current.children[index] to be a new Node
        current = current.children[index]

You can easily augment this pseudocode to fit your needs. 您可以轻松扩充此伪代码以满足您的需求。 For example, if you want to return false whenever insertion isn't successful: 例如,如果要在插入不成功时返回false:

  • Return false if the input string is null 如果输入字符串为null,则返回false
  • Return false if the input string contains invalid characters 如果输入字符串包含无效字符,则返回false

Now, here is some higher-level pseudocode for remove. 现在,这里有一些更高级别的伪代码用于删除。

Remove(String str)
    Node current = null
    for each character in str
        int index = getIndex(character)
        current = current.children[index] 

    // At this point, we found the node we want to remove. However, we want to 
    // delete as many ancestor nodes as possible. We can delete an ancestor node 
    // if it is not need it any more. That is, we can delete an ancestor node 
    // if it has exactly one child. 

    Node ancestor = current
    while ancestor is not null
        if ancestor has 2 or more children
            break out of loop 
        else if ancestor has less than 2 children
            Node grandAncestor = ancestor.parent
            if grandAncestor is not null
                reinitialize grandAncestor.children // this has the effect of removing ancestor

        ancestor = ancestor.parent   

At a very high level, we follow the input string to the node we want to remove. 在非常高的级别,我们将输入字符串跟随到我们要删除的节点。 After this, we traverse up the tree following parent pointers and delete every node with 1 child (since it is no longer needed). 在此之后,我们在父指针之后遍历树并删除具有1个子节点的每个节点(因为不再需要它)。 Once we reach a node with 2 children, we stop. 一旦我们到达有2个孩子的节点,我们就会停下来。

Like Insert, we can easily augment this pseudocode to return false whenever deletion isn't successful: 与Insert一样,我们可以轻松地扩充此伪代码,以便在删除失败时返回false:

  • Return false if the input string is null 如果输入字符串为null,则返回false
  • Return false if the input string contains invalid characters 如果输入字符串包含无效字符,则返回false
  • Return false if the input string leads to a Node which doesn't exist 如果输入字符串指向不存在的节点,则返回false

It is easiest to implement delete if your Node class has a parent field. 如果您的Node类具有父字段,则最容易实现删除。 However, it is possible to implement the method without parent points, but it is more difficult. 但是,可以在没有父点的情况下实现该方法,但是更加困难。 You can see an example of the trickier implementation here . 你可以在这里看到一个棘手的实现的例子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM