T9词典如何运作?它背后的数据结构是什么。如果我们输入'4663',当我们按下按钮时我们会'好',然后'去'然后'回家'等...
编辑:如果用户键入46,那么它应显示'go',按下箭头时应显示'gone'等...
答案 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非常好地解释:
答案 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)哈希表查找。