Java 使用二叉树查找字谜

Java 使用二叉树查找字谜,java,binary-tree,Java,Binary Tree,我目前正在尝试创建一个方法,该方法使用二叉树查找用户输入的单词的字谜 如果树不包含单词的任何其他字谜(即,如果键不在树中或关联链表中的唯一元素是用户提供的单词),则会打印消息“未找到字谜” 例如,如果键“opst”出现在树中,并且有一个包含单词“spot”、“pots”和“tops”的关联链表,并且用户给出了单词“spot”,那么程序应该打印“pots”和“tops”(而不是spot) public boolean find(K thisKey,T thissement){ 返回find(roo

我目前正在尝试创建一个方法,该方法使用二叉树查找用户输入的单词的字谜

如果树不包含单词的任何其他字谜(即,如果键不在树中或关联链表中的唯一元素是用户提供的单词),则会打印消息“未找到字谜” 例如,如果键“opst”出现在树中,并且有一个包含单词“spot”、“pots”和“tops”的关联链表,并且用户给出了单词“spot”,那么程序应该打印“pots”和“tops”(而不是spot)

public boolean find(K thisKey,T thissement){
返回find(root、thisKey、thisement);
}
公共布尔查找(当前节点、K thisKey、T thissement){
如果(当前==null)
返回false;
否则{
int comp=当前键比较(此键);
如果(补偿>0)
返回find(current.left、thisKey、thisement);

否则,如果(comp有点不清楚到底是什么绊倒了你(除了“我写了一个很好的find方法,但不允许使用它”),那么我认为最好的办法是从头开始

我想你会发现,一旦你以正确的方式构造了数据,实际的算法就会相对容易地遵循(许多计算机科学问题都有这个特点)

你有三件事:

1) 许多链表,每个链表都包含一组字母的字谜。我假设您可以根据需要生成这些列表

2) 二叉树,将字符串(键)映射到由这些字符串生成的字谜列表。同样,我假设您能够对这些树执行基本操作——添加元素、按键查找元素,等等

3) 用户输入的字符串

Insight:一组字母的字谜构成一个等价类。这意味着字谜列表的任何成员都可以用作与列表关联的键。此外,这意味着您不需要在树中存储指向同一列表的多个键(前提是我们在构建数据结构方面有点聪明;见下文)

具体来说,不需要将“spot”和“opts”都作为指向同一列表的树中的键,因为一旦可以使用“spot”的任何字谜找到列表,就可以得到“spot”的所有字谜

巧妙地结构化数据:根据我们的洞察力,假设我们的树中每个唯一的字谜集只包含一个键。因此“opts”映射到{“opts”、“pots”、“spot”等。)。如果我们的用户给我们一个字符串,而我们没有将其用作字谜集的键,会发生什么情况?如果用户键入“spot”,我们如何确定,我们应该找到由“opts”键控的列表

答案是对存储在数据结构中的数据进行规范化。这是一种计算机科学的说法,即我们强制执行关于如何存储数据的任意规则。(规范化数据是一种有用的技术,在许多不同的计算机科学领域反复出现。)第一条规则是,我们的树中只有一个键映射到给定的链表。第二,如果我们确保我们实际存储的每个键都是可预测的——也就是说,我们知道即使用户键入“spot”,我们也应该搜索“opts”呢

有很多方法可以实现这种可预测性——一个简单的方法是确保每个键的字母都是按字母顺序排列的。然后,我们知道每一组字谜都将由(唯一的!)按字母顺序排在第一位的集合成员。始终执行此规则使搜索树变得容易--我们知道,无论用户给我们什么字符串,我们想要的键都是按字母顺序排列用户输入的字符串

把它放在一起:我将在这里提供高级算法,使其更加具体

1) 从用户处获取字符串(请保留此字符串,我们稍后将需要它)

2) 将此字符串转换为遵循我们的规范化方案的搜索键 (您可以在“K”类的构造函数中执行此操作,从而确保您的程序中不会有任何非规范化键。)

3) 在树中搜索该键,并获取与之关联的链表。此列表包含用户输入字符串的每个字谜

4) 打印列表中不是用户原始字符串的每一项(请参见为什么要将字符串放在手边?)


外卖

通常情况下,你的数据会有一些让你变得聪明的特殊功能。在这种情况下,事实上,一个字谜列表的任何成员都可以是我们为该列表存储的唯一键

规范化您的数据会给您带来可预测性,并允许您有效地进行推理。如果每个键都可以是其字谜列表的任意成员,“查找”算法会有多困难


推论:完全正确地获取数据结构(我存储的是什么?各部分如何连接?如何表示?)将使编写算法变得更加容易。

如何对单词中的字符进行排序,然后进行比较。

您编写的方法最好称为
包含
('is the key in this tree?')。要使此方法成为
find
方法,它应该返回找到的内容。
public boolean find(K thisKey, T thisElement){
    return find(root, thisKey, thisElement);
}

public boolean find(Node current, K thisKey, T thisElement){
    if (current == null)
        return false;
    else{
        int comp = current.key.compareTo(thisKey);
        if (comp>0)
            return find(current.left, thisKey, thisElement);
        else if(comp<0)
            return find(current.right, thisKey, thisElement);
        else{
            return current.item.find(thisElement);
        }
    }
}