【问题标题】:Lexicographic sorting with a Trie使用 Trie 进行字典排序
【发布时间】:2014-02-20 04:43:32
【问题描述】:

根据维基百科,关于特里:

一组键的字典排序可以通过一个简单的基于trie的算法来完成,如下所示:

  • 在 trie 中插入所有键。
  • 通过前序遍历的方式输出 trie 中的所有键,这导致输出按字典顺序递增。

但是,这是我对标准 trie 实现的测试:

Trie trie = new Trie();
trie.add("doll");
trie.add("ball");
trie.add("bat");
trie.add("dork");
trie.add("dorm");
trie.add("send");
trie.add("sense");
trie.add("sent");

预购打印输出:

     public List<String> allWords(){

    List<String> words = new ArrayList<String>();

    if(root == null){
        return words;
    }

    StringBuilder prefix = new StringBuilder();
    getAllWords(root.children,prefix,words);

    return words;
}

// depth first search
private void getAllWords(List<TrieNode> children, StringBuilder prefix,  List<String> words){

    for(int i= 0; i<children.size(); i++){
        TrieNode child = children.get(i);
        if(!child.isWord_){
            prefix.append(child.data_);
            allWordsHelper(child.children, prefix, words);
        }else{
            prefix.append(child.data_);
            words.add(prefix.toString());
        }
        prefix.deleteCharAt(prefix.length()-1);
    }
}

而输出顺序为:doll dork dorm ball bat send sense sent

“字典排序”是什么意思?似乎输出顺序与插入顺序更相关,而不是字典顺序。我有什么问题吗? 以这棵树为例,预购打印输出将是“toteated 10 a inn”。字典顺序在哪里?

【问题讨论】:

  • 打印输出时是否进行了预购遍历?
  • 是的,预购。由于“娃娃”是先插入的,因此即使在预订时也必须先输出。在根下,第一级字符是'd b s'。通过预购,它首先打印所有带有 'd' 前缀的单词。
  • 想想标准的 Trie 数据结构和上面描述的两步算法,没有任何信息可以保证字典顺序。这怎么可能?
  • 如果您进行中序遍历并按排序顺序访问每个节点的子节点,您应该按排序顺序取回所有元素。您能否向我们展示您用于中序遍历和将节点存储在 trie 中的代码?
  • 但是wiki说实现词典排序是预购的。

标签: java trie


【解决方案1】:

关于使用尝试的字典排序的正确说法是:

假设节点的子节点按边标签排序,则 trie 中节点的前序与它们所代表的字符串的字典顺序相同。

现在,如果您在代码中尝试过此操作,预排序遍历应该会按字典顺序为您提供字符串。

这里有一个例子的参考:http://www.cs.helsinki.fi/u/tpkarkka/opetus/12s/spa/lecture02.pdf

【讨论】:

    【解决方案2】:

    按照我的说法,应该是Inorder遍历。可以遍历 trie,首先处理所有键值小于 root 值的分支,然后打印 root 值,最后打印所有值大于 root 值。这是标准 inorder 遍历,但我要说的唯一一点是,您必须编写自定义逻辑来处理所有具有小于root 键的键的分支,这在常规二叉树中会只是 root.left,但由于 trie 中没有左/右,我们将不得不退回到 BST 中左和右的本质。(其 inorder 也输出按字典顺序排序的值。`)

    【讨论】:

      【解决方案3】:

      也可以通过TreeMap来完成-

      import java.util.Map;
      import java.util.TreeMap;
      
      class TrieNodeTreeMap{
          Map<Character, TrieNodeTreeMap> children;
          String key;
      
          public TrieNodeTreeMap(){
              key = null;
              children = new TreeMap<>();
          }
      }
      public class LexicographPrint {
          public static TrieNodeTreeMap root;
      
          public static void main(String[] args) {
      
              root = new TrieNodeTreeMap();
              //String s = "lexicographic sorting of a set";
              String s = "lexicographic sorting of a set of keys can be accomplished with " +
                      "a simple trie based algorithm we insert all keys in a trie output " +
                      "all keys in the trie by means of preorder traversal which results " +
                      "in output that is in lexicographically increasing order preorder " +
                      "traversal is a kind of depth first traversal";
              String dict[] = s.split(" ");
              for (String word : dict){
                  insertion(root,word);
              }
      
              lexicographlySort(root);
          }
      
          private static void insertion(TrieNodeTreeMap root, String str){
              TrieNodeTreeMap curr = root;
      
              for (char ch : str.toCharArray()){
                  if (!curr.children.containsKey(ch)){
                      curr.children.put(ch, new TrieNodeTreeMap());
                  }
      
                  curr  = curr.children.get(ch);
              }
      
              curr.key = str;
          }
      
          private static void lexicographlySort(TrieNodeTreeMap root){
              TrieNodeTreeMap curr = root;
              if (curr == null)
                  return;
      
              for (Map.Entry<Character, TrieNodeTreeMap> entry : curr.children.entrySet()){
                  TrieNodeTreeMap tmp = entry.getValue();
                  if (tmp.key != null)
                      System.out.println(tmp.key);
                  lexicographlySort(entry.getValue());
              }
          }
      }
      

      【讨论】:

      • @Naveen kumar singh 请用适当的解释详细说明你的答案。
      猜你喜欢
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多