包含所有建议的三元搜索树在C#中自动完成

时间:2011-11-21 12:49:28

标签: c# algorithm search autocomplete ternary-search-tree

我想知道是否可以修改三元搜索树来检查单词是否存在 AND 查找以该单词开头的所有单词(或者以该单词结束?)? 例如do => dog dogs等。

从这个site是一个示例代码。首先将所有单词加载到三元树然后我们可以使用方法来检查单词是否存在。

public class TernaryTree
{
    private Node m_root = null;

    private void Add(string s, int pos, ref Node node)
    {
        if (node == null) { node = new Node(s[pos], false); }

        if (s[pos] < node.m_char) { Add(s, pos, ref node.m_left); }
        else if (s[pos] > node.m_char) { Add(s, pos, ref node.m_right); }
        else
        {
            if (pos + 1 == s.Length) { node.m_wordEnd = true; }
            else { Add(s, pos + 1, ref node.m_center); }
        }
    }

    public void Add(string s)
    {
        if (s == null || s == "") throw new ArgumentException();

        Add(s, 0, ref m_root);
    }

    public bool Contains(string s)
    {
        if (s == null || s == "") throw new ArgumentException();

        int pos = 0;
        Node node = m_root;
        while (node != null)
        {
            int cmp = s[pos] - node.m_char;
            if (s[pos] < node.m_char) { node = node.m_left; }
            else if (s[pos] > node.m_char) { node = node.m_right; }
            else
            {
                if (++pos == s.Length) return node.m_wordEnd;
                node = node.m_center;
            }
        }

        return false;
    }
}

class Node
{
    internal char m_char;
    internal Node m_left, m_center, m_right;
    internal bool m_wordEnd;

    public Node(char ch, bool wordEnd)
    {
        m_char = ch;
        m_wordEnd = wordEnd;
    }
}

这让我心里很满意:(
获得这些话的任何方式都可以是任何东西。但是我在那个级别的算法中很弱.. 我希望我不会重复任何有关此问题的问题。 任何建议,我将不胜感激。

1 个答案:

答案 0 :(得分:1)

可以使用三元树,但我不建议(不容易这样做)。

我认为您可以使用两种不同的方法:

A。,使用标准的 Trie 代替三元树,因此无论您在Trie中拥有多少项目,您的搜寻时间都将被视为不变。 C#实现是可以实现的,但请记住,Trie需要平均/高级别的算法知识。

B。,使用标准的排序数组(string [])。由于您的要求只是根据前缀创建自动填充,请将所有单词存储在字符串[]中,然后在其上开始 binary search 。 寻道时间不是常数而是对数,但即使你在该阵列中存储了数百万个单词,每次搜索也可以在几分之一毫秒内进行测量(例如,如果你在该数组中有一百万字,那么只有20个操作需要找到你要找的那个)。即使二进制搜索不成功,您也会得到一个最接近匹配的索引(但索引将为负值,表示匹配不成功)。所以,在这个数组中:

A 
C
D 
E

如果你搜索B,你会得到索引0,指向A.如果你开始加强,你会看到'B'之后的项目(或你的例子中的'dog')。

因此,即使您在二进制搜索后进行完全匹配或部分匹配,也要继续列出数组中的项目,直到搜索的关键字为字典单词的 at the beginning