C# 是否有可能生成所有可在三元搜索树中查找的可能术语?
从我对三元搜索树的理解来看,它们在可以搜索和找到的项目中是逆确定性的(不确定是否有正确的术语)。我的意思是,如果你为cat,bicycle,axis创建一个三元树,你给某人这个三元树,他应该能够从中扣除这三个词 这是正确的吗 我这样问是因为我有一个三元树结构,其中包含诸如ISMAP、SELECTED和COMPACT(实际上是HTML4的属性)之类的词,我想知道是否可以得到存储在该树中的项目的完整列表(原始文档已经不见了)。结构如下所示:C# 是否有可能生成所有可在三元搜索树中查找的可能术语?,c#,.net,algorithm,reverse-engineering,ternary-search-tree,C#,.net,Algorithm,Reverse Engineering,Ternary Search Tree,从我对三元搜索树的理解来看,它们在可以搜索和找到的项目中是逆确定性的(不确定是否有正确的术语)。我的意思是,如果你为cat,bicycle,axis创建一个三元树,你给某人这个三元树,他应该能够从中扣除这三个词 这是正确的吗 我这样问是因为我有一个三元树结构,其中包含诸如ISMAP、SELECTED和COMPACT(实际上是HTML4的属性)之类的词,我想知道是否可以得到存储在该树中的项目的完整列表(原始文档已经不见了)。结构如下所示: internal static byte [] htmlA
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,
};
我认为算法是这样的
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代码。我使用了这篇维基百科文章中的树
我将它表示为一个数组,其中根是元素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, "");
}
}
}
数据结构并不完全是三元树,因为第三个分支是隐式的(即当前条目之后的下一个条目)。这有点像是在二叉树结构中实现的。每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,65,0,0,0
之后的12个条目是A,0,0,0
。它和接下来的5个条目(65,67,84,73,79,78)显然对应于字符串动作
。在右偏移量之后,#0之后有77个条目,我们有78,8,48,0,79,36,0,0,0,83,30,55,0,72,0,0,0,0,65,
或带有分支的N、O和S条目,然后是没有显式分支的H、A、D、E条目,以生成NOSHADE
当您沿着树向叶子方向移动时,将字母添加到当前字符串(如在trie中遍历),当您返回(远离叶子)时,将字母从当前字符串的末尾删除。谢谢您的帮助。所以至少你确认了我认为是可能的。现在我将尝试实现它。我放入一个示例树和一些C代码来演示如何实现它。我不知道如何读取数组,但是如果你知道的话,这段代码基本上应该可以工作。根据@jwpat7答案中的信息——只需重新实现hasleet、LeftKid等,它也应该可以在你的数组上工作。
cute
cup
at
as
he
us
i