T9类型字典背后的数据结构

时间:2010-04-04 09:26:58

标签: algorithm data-structures mobile

T9词典如何运作?它背后的数据结构是什么。如果我们输入'4663',当我们按下按钮时我们会'好',然后'去'然后'回家'等...

编辑:如果用户键入46,那么它应显示'go',按下箭头时应显示'gone'等...

6 个答案:

答案 0 :(得分:47)

它可以通过多种方式实现,其中之一是Trie。路由由数字表示,节点指向单词集合。

它也可以使用嵌套哈希表来实现,hash table的键是一个字母,算法计算所有可能的路径(O(3 ^ n)路径)。

答案 1 :(得分:13)

4663

转换为

{G,H,I} {M,N,O} {M,N,O} {d,E,F}

T9的工作原理是从第一个可能的字母开始按顺序过滤可能性。因此,您的示例中的第一步是将字典列表过滤为以G,H或I开头的所有单词。下一步,取出该列表并按M,N,O过滤第二个字母。依此类推......

答案 2 :(得分:4)

我认为T9正在使用基于位图的Trie。在第一级有一个32位(我假设它们扩展到32)字,其中每个位代表一个字母。所有作为单词的起始字母有效的字母都设置了它们的位。

在下一级中,对于在上一级中设置的每个位,都有一个32位映射。在这些地图中,如果相应的字母作为单词中的第二个字母有效,则每个位都会被设置,起始字母由第一个级别决定。

然后结构继续。每个字母使用一位数可以实现非常高效的存储。然而,寻址方案必须具有挑战性。对于短词,可能还会使用上述模式进行某种优化,而对于较长的词则使用其他内容。

答案 3 :(得分:4)

我想,就像之前那些T9使用trie一样,链接用位图表示(每个字母1位)。这被称为简洁的数据结构,正如Steve Hanov非常好地解释:

http://stevehanov.ca/blog/index.php?id=120

答案 4 :(得分:2)

使用Trie实现C#

        public interface ICellT9
        {
            void Add(string a_name);

            List<string> GetNames(string a_number);
        }

        public class Cell : ICellT9
        {
            private Dictionary<int, Cell> m_nodeHolder;
            private List<string> m_nameList;

            public Cell()
            {
                m_nameList = new List<string>();
                m_nodeHolder = new Dictionary<int, Cell>();

                for (int i = 2; i < 10; i++)
                {
                    m_nodeHolder.Add(i, null);
                }
            }

            public void Add(string a_name)
            {
                Add(a_name, a_name);
            }

            private void Add(string a_name, string a_originalName)
            {
                if (string.IsNullOrEmpty(a_name) && 
                   (string.IsNullOrEmpty(a_originalName) == false))
                {
                    m_nameList.Add(a_originalName);
                }
                else
                {
                    int l_firstNumber = CharToNumber(a_name[0].ToString());

                    if (m_nodeHolder[l_firstNumber] == null)
                    {
                        m_nodeHolder[l_firstNumber] = new Cell();
                    }

                    m_nodeHolder[l_firstNumber].Add(a_name.Remove(0, 1), a_originalName);
                }
            }

            public List<string> GetNames(string a_number)
            {
                List<string> l_result = null;

                if (string.IsNullOrEmpty(a_number))
                {
                    return l_result;
                }

                int l_firstNumber = a_number[0] - '0';

                if (a_number.Length == 1)
                {
                    l_result = m_nodeHolder[l_firstNumber].m_nameList;
                }
                else if(m_nodeHolder[l_firstNumber] != null)
                {
                    l_result = m_nodeHolder[l_firstNumber].GetNames(a_number.Remove(0, 1));
                }

                return l_result;

            }

            private int CharToNumber(string c)
            {
                int l_result = 0;

                if (c == "a" || c == "b" || c == "c")
                {
                    l_result = 2;
                }
                else if (c == "d" || c == "e" || c == "f")
                {
                    l_result = 3;
                }
                else if (c == "g" || c == "h" || c == "i")
                {
                    l_result = 4;
                }
                else if (c == "j" || c == "k" || c == "l")
                {
                    l_result = 5;
                }
                else if (c == "m" || c == "n" || c == "o")
                {
                    l_result = 6;
                }
                else if (c == "p" || c == "q" || c == "r" || c == "s")
                {
                    l_result = 7;
                }
                else if (c == "t" || c == "u" || c == "v")
                {
                    l_result = 8;
                }
                else if (c == "w" || c == "x" || c == "y" || c == "z")
                {
                    l_result = 9;
                }

                return l_result;
            }
        }

答案 5 :(得分:1)

我可能通过从字典开始,然后(对于每个单词)将单词推到由可能形成单词的数字键入的列表上。

然后,您可能需要以某种方式对结果列表进行排序,因此在不太可能的单词之前出现更多可能的单词(如果您有空格,我还会为计数器包含一个小区域,所以我们可以逐步重新排序这些OR只是简单地将最后一次用于建议列表的前面,所以我们随着时间的推移倾向于给用户一个更好的答案。)

这样,当你有4663作为输入时,你可以很简单地检索相关的链表,大概是O(1)哈希表查找。