【问题标题】:Is it possible to generate all possible terms findable in a ternary search tree?是否可以生成可在三元搜索树中找到的所有可能项?
【发布时间】:2011-12-29 22:06:36
【问题描述】:

根据我对三元搜索树的理解,它们在可以搜索和找到的项目中是反向确定的(不确定术语是否正确)。我的意思是,如果你为 catbicycleaxis 创建一个三叉树,然后给某人三叉树,他应该能够从中扣除这三个词。

这对吗?

我在问,因为我有一个三元树结构,其中包含诸如 ISMAP、SELECTED 和 COMPACT 之类的词(实际上是 HTML 4 的属性),我想知道是否可以获得存储在该树中的项目的完整列表(原始文档不见了)。结构如下:

internal static byte [] htmlAttributes = {
   72,5,77,0, 82,0,0,0, 69,0,0,0, 70,0,0,0, 0,0,0,1, 67,12,40,0, 79,7,0,0,
   77,31,0,0, 80,0,0,0, 65,0,0,0, 67,0,0,0, 84,0,0,0, 0,0,0,2, 73,11,18,0,
   84,0,0,0, 69,0,0,0, 0,0,0,1, 65,0,0,0, 67,0,0,0, 84,0,0,0, 73,0,0,0,
   79,0,0,0, 78,0,0,0, 0,0,0,1, 72,0,0,0, 69,0,0,0, 67,0,0,0, 75,0,0,0,
   69,0,0,0, 68,0,0,0, 0,0,0,2, 76,0,0,0, 65,0,0,0, 83,0,0,0, 83,0,0,0,
   73,0,0,0, 68,0,0,0, 0,0,0,1, 68,0,0,0, 69,0,0,0, 66,0,0,0, 65,0,0,0,
   83,0,0,0, 69,0,0,0, 0,0,0,1, 68,0,28,0, 69,7,15,0, 67,0,22,0, 76,0,0,0,
   65,0,0,0, 82,0,0,0, 69,0,0,0, 0,0,0,2, 65,0,0,0, 84,0,0,0, 65,0,0,0,
   0,0,1,1, 83,0,0,0, 82,0,0,0, 67,0,0,0, 0,0,0,1, 73,0,0,0, 83,0,0,0,
   65,0,0,0, 66,0,0,0, 76,0,0,0, 69,0,0,0, 68,0,0,0, 0,0,0,2, 70,0,0,0,
   69,0,0,0, 82,0,0,0, 0,0,0,2, 70,0,0,0, 79,0,0,0, 82,0,0,0, 0,0,0,1,
   78,8,48,0, 79,36,0,0, 83,30,55,0, 72,0,0,0, 65,0,0,0, 68,0,0,0, 69,0,0,0,
   0,0,0,2, 77,9,0,0, 85,0,0,0, 76,0,0,0, 84,0,0,0, 73,0,0,0, 80,0,0,0,
   76,0,0,0, 69,0,0,0, 0,0,0,2, 73,0,6,0, 83,0,0,0, 77,0,0,0, 65,0,0,0,
   80,0,0,0, 0,0,0,2, 76,0,0,0, 79,0,0,0, 78,0,0,0, 71,0,0,0, 68,0,0,0,
   69,0,0,0, 83,0,0,0, 67,0,0,0, 0,0,0,1, 72,0,9,0, 82,0,0,0, 69,0,0,0,
   70,0,0,0, 0,0,0,2, 65,0,0,0, 77,0,0,0, 69,0,0,0, 0,0,0,1, 82,0,0,0,
   69,0,0,0, 83,0,0,0, 73,0,0,0, 90,0,0,0, 69,0,0,0, 0,0,0,2, 82,14,22,0,
   69,0,0,0, 65,0,0,0, 68,0,0,0, 79,0,0,0, 78,0,0,0, 76,0,0,0, 89,0,0,0,
   0,0,0,2, 87,0,0,0, 82,0,0,0, 65,0,0,0, 80,0,0,0, 0,0,0,2, 80,0,0,0,
   82,0,0,0, 79,0,0,0, 70,0,0,0, 73,0,0,0, 76,0,0,0, 69,0,0,0, 0,0,0,1,
   83,0,12,0, 82,3,0,0, 67,0,0,0, 0,0,0,1, 69,0,0,0, 76,0,0,0, 69,0,0,0,
   67,0,0,0, 84,0,0,0, 69,0,0,0, 68,0,0,0, 0,0,0,2, 85,0,0,0, 83,0,0,0,
   69,0,0,0, 77,0,0,0, 65,0,0,0, 80,0,0,0, 0,0,0,1, 
};

【问题讨论】:

    标签: c# .net algorithm reverse-engineering ternary-search-tree


    【解决方案1】:

    我认为算法是这样的

    printOutWords(root, wordSoFar)
         if (!root.hasMiddle)
            print wordSoFar + root.char
    
         if (root.hasMiddle)
            printOutWords(root.middle, wordSoFar + root.char)
         if (root.hasLeft)
            printOutWords(root.left, wordSoFar)
         if (root.hasRight)
            printOutWords(root.right, wordSoFar)
    

    然后,开始

    printOutWords(ternaryTree, "")
    

    我不知道如何解码你的数组,但如果你能实现这些操作,我认为是这样的。

    好的,这里有一些基于简单数组表示的 C# 代码。我使用了这篇维基百科文章中的树

    http://en.wikipedia.org/wiki/Ternary_search_tree

    我将它表示为一个数组,其中根为元素 0,其子元素为 1、2、3。1 的子元素为 4、5、6,依此类推。 '\0' 用于表示没有孩子了。算法同上。

    using System;
    using System.Text;
    
    namespace TreeDecode
    {
        class Program
        {
            // http://en.wikipedia.org/wiki/Ternary_search_tree
            //The figure below shows a ternary search tree with the strings "as", "at", "cup", "cute", "he", "i" and "us":
            internal static char[] searchTree = {
                                                                                   'c', 
                                  'a',                                             'u',                                               'h', 
                   '\0',          't',          '\0',            '\0',             't',           '\0',              '\0',            'e',            'u',
             '\0','\0','\0', 's','\0','\0','\0','\0','\0',  '\0','\0','\0',  'p','e','\0',   '\0','\0','\0',    '\0','\0','\0', '\0','\0','\0',   'i','s','\0',
            };
    
           static void printOutWords(char[] tree, int root, string wordSoFar) {
              if (!HasMiddle(tree, root))
                  Console.WriteLine(wordSoFar + CharAt(tree, root));
    
              if (HasMiddle(tree, root))
                  printOutWords(tree, MiddleKid(root), wordSoFar + CharAt(tree, root));
              if (HasLeft(tree, root))
                  printOutWords(tree, LeftKid(root), wordSoFar);
              if (HasRight(tree, root))
                  printOutWords(tree, RightKid(root), wordSoFar);
    
            }    
    
            private static int RightKid(int root)
            {
                return root * 3 + 3;            
            }
    
            private static bool HasRight(char[] tree, int root)
            {
                int rightIndex = RightKid(root);
                return (rightIndex < tree.Length && tree[rightIndex] != 0);
            }
    
            private static int LeftKid(int root)
            {
                return root * 3 + 1;
            }
    
            private static bool HasLeft(char[] tree, int root)
            {
                int leftIndex = LeftKid(root);
                return (leftIndex < tree.Length && tree[leftIndex] != 0);
            }
    
            private static int MiddleKid(int root)
            {
                return root * 3 + 2;
            }
    
            private static bool HasMiddle(char[] tree, int root)
            {
                int middleIndex = MiddleKid(root);
                return (middleIndex < tree.Length && tree[middleIndex] != 0);
            }
    
            private static int NumKids(char[] tree, int root)
            {
                return (HasMiddle(tree, root) ? 1 : 0) + (HasRight(tree, root) ? 1 : 0) + (HasLeft(tree, root) ? 1 : 0);
            }
    
    
            private static string CharAt(char[] tree, int root)
            {
                return new String(tree[root], 1);
            }
    
    
            static void Main(string[] args)
            {
                printOutWords(searchTree, 0, "");
            }
        }
    }
    

    打印出来

    cute
    cup
    at
    as
    he
    us
    i
    

    【讨论】:

    • 感谢您的帮助。所以至少你确认了我认为是可能的。现在我将尝试实现它。
    • 我放入了一个示例树和一些 C# 代码来展示如何做到这一点。我不知道如何读取你的数组,但如果你知道,这段代码应该基本上可以工作。
    • 鉴于@jwpat7 的答案中的信息——只需重新实现 HasLeft、LeftKid 等,它也应该适用于您的阵列。
    【解决方案2】:

    数据结构并不完全是三叉树,因为第三个分支是隐式的(,当前条目之后的下一个条目)。它有点像在二叉树结构中实现的trie。每 4 个数字对应一个类似 struct { char letter, Loff, Roff, flag} 的结构。例如,条目 0 = 72,5,77,0 是字母 'H',左偏移 5,右偏移 77,标志 0(可能意味着不是终端)。在左偏移之后,#0 之后的 5 个条目我们有 67,12,40,0,即 C, 12, 40, 0; #5 之后的 12 个条目,65,0,0,0A,0,0,0。它和接下来的 5 个条目(带有 65、67、84、73、79、78)显然对应于字符串 ACTION。在右偏移之后,#0 之后的 77 个条目我们有 78,8,48,0, 79,36,0,0, 83,30,55,0, 72,0,0,0, 65,... 或带有分支的 N、O 和 S 条目,然后是没有明确分支的 H、A、D、E 条目,以构成 NOSHADE

    当您沿着树向叶子移动时,将字母添加到当前字符串(如在 trie 中遍历),当您返回(远离叶子)时,从当前字符串的末尾删除字母。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-07
      • 1970-01-01
      • 2019-05-20
      • 2014-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多