通过修改二进制搜索算法来改进它,使其在大量单词(单词列表)中搜索单词时工作得更快
Improving the binary search algorithm by modifying it so that it works faster when searching for a word in large number of words (word list)
我想从已排序的单词列表中搜索特定单词。我的单词列表包含 100,000 个单词。
为了提高二分查找算法的性能,我想稍微修改一下。例如,如果我想搜索单词 "apple" 而不是对整个单词列表应用二进制搜索算法。我将仅将其应用于以字母 'a' 开头的单词。如果我将单词列表加载到数组或向量中,我知道我会从索引 0 开始搜索。问题是我不知道以字母 'a' 开头的单词的最后一个索引是什么。
关于如何知道最后一个索引的任何想法?
这将是第一个不以 'a' 开头的单词的索引。建立一个顶级索引,给出每个字符的起始索引,并根据需要使用它来创建搜索范围。
您可以将单词列表分割成 'bins',特定 bin 中的每个单词都以相同的字母开头。根据搜索词的首字母,选择合适的 bin 进行搜索。这只需要对原始列表进行一次性预处理。
您可以考虑一个更简单的相关想法:interpolation search:它类似于人类在电话簿中搜索特定姓名的方式,即电话簿条目排序的键值。
In each search step it calculates where in the remaining search space the sought item might be, based on the key values at the bounds of the search space and the value of the sought key, usually via a linear interpolation.
The key value actually found at this estimated position is then compared to the key value being sought. If it is not equal, then depending on the comparison, the remaining search space is reduced to the part before or after the estimated position. This method will only work if calculations on the size of differences between key values are sensible.
在用于插值的线性尺度上数据均匀分布的假设下,性能可以显示为O(log log n)
。
Practical performance of interpolation search depends on whether the reduced number of probes is outweighed by the more complicated calculations needed for each probe. It can be useful for locating a record in a large sorted file on disk, where each probe involves a disk seek and is much slower than the interpolation arithmetic.
但是维护辅助索引/桶也是如此。
其他人的建议,如果您概括的话,就是构造一个 trie,这是个好主意。
trie 的优点是您可以对前几个字母使用索引,这比二进制搜索更快。
当然,你会展开它。
您可能会考虑的另一个想法是 Bentley 的展开二分搜索,它看起来像这样:
i = 0;
if (word >= dict[i + (1<<16)]){i += (1<<16);}
if (word >= dict[i + (1<<15)]){i += (1<<15);}
....
if (word >= dict[i + (1<<1)]){i += (1<<1);}
if (word >= dict[i + (1<<0)]){i += (1<<0);}
其中 word
是您要查找的词,dict
是您排序的字典,它的大小是 1<<17
个字符串。
它会在 17 次比较中找到您要查找的字典条目。
您可能必须通过在末尾放置 "0x7f"
标记字符串来将字典填充为 2 的幂。
另一种方法是使索引操作更智能,因此任何超过字典大小的索引都会为您提供标记字符串。
请记住,比较并不昂贵。
如果两个单词的第一个字符不同,则只需要比较第一个字符。
如果第一个字符相同,第二个字符不同,则只需要比较两个字符。
在你快完成之前,你不要比较整个单词。
我建议你实施 TRIE instead of implementing binary search algorithm. For example: each letter will be node of TRIE. The time complexity to build TRIE is O(W*L). W is number of word. L is average length of the word. When you find the word from TRIE 它需要 O(L).
您应该使用 Trie ADT
以获得良好的搜索操作性能。其中,只要用户输入'X',就会显示所有以'X'开头的标题。此功能与您在 Google、YouTube 或 Netflix 上看到的非常相似。显然,您可以对 Trie
的构造施加 more/fewer 约束,以随心所欲地塑造它。为什么 Trie 与数组?尝试更快。继续阅读以了解更多信息。
这里是Wikipedia article on Tries. An implementation of a Trie ADT in Java. An implementation of a T9 dictionary (like the good old days) in C.
我想从已排序的单词列表中搜索特定单词。我的单词列表包含 100,000 个单词。 为了提高二分查找算法的性能,我想稍微修改一下。例如,如果我想搜索单词 "apple" 而不是对整个单词列表应用二进制搜索算法。我将仅将其应用于以字母 'a' 开头的单词。如果我将单词列表加载到数组或向量中,我知道我会从索引 0 开始搜索。问题是我不知道以字母 'a' 开头的单词的最后一个索引是什么。 关于如何知道最后一个索引的任何想法?
这将是第一个不以 'a' 开头的单词的索引。建立一个顶级索引,给出每个字符的起始索引,并根据需要使用它来创建搜索范围。
您可以将单词列表分割成 'bins',特定 bin 中的每个单词都以相同的字母开头。根据搜索词的首字母,选择合适的 bin 进行搜索。这只需要对原始列表进行一次性预处理。
您可以考虑一个更简单的相关想法:interpolation search:它类似于人类在电话簿中搜索特定姓名的方式,即电话簿条目排序的键值。
In each search step it calculates where in the remaining search space the sought item might be, based on the key values at the bounds of the search space and the value of the sought key, usually via a linear interpolation.
The key value actually found at this estimated position is then compared to the key value being sought. If it is not equal, then depending on the comparison, the remaining search space is reduced to the part before or after the estimated position. This method will only work if calculations on the size of differences between key values are sensible.
在用于插值的线性尺度上数据均匀分布的假设下,性能可以显示为O(log log n)
。
Practical performance of interpolation search depends on whether the reduced number of probes is outweighed by the more complicated calculations needed for each probe. It can be useful for locating a record in a large sorted file on disk, where each probe involves a disk seek and is much slower than the interpolation arithmetic.
但是维护辅助索引/桶也是如此。
其他人的建议,如果您概括的话,就是构造一个 trie,这是个好主意。 trie 的优点是您可以对前几个字母使用索引,这比二进制搜索更快。 当然,你会展开它。
您可能会考虑的另一个想法是 Bentley 的展开二分搜索,它看起来像这样:
i = 0;
if (word >= dict[i + (1<<16)]){i += (1<<16);}
if (word >= dict[i + (1<<15)]){i += (1<<15);}
....
if (word >= dict[i + (1<<1)]){i += (1<<1);}
if (word >= dict[i + (1<<0)]){i += (1<<0);}
其中 word
是您要查找的词,dict
是您排序的字典,它的大小是 1<<17
个字符串。
它会在 17 次比较中找到您要查找的字典条目。
您可能必须通过在末尾放置 "0x7f"
标记字符串来将字典填充为 2 的幂。
另一种方法是使索引操作更智能,因此任何超过字典大小的索引都会为您提供标记字符串。
请记住,比较并不昂贵。 如果两个单词的第一个字符不同,则只需要比较第一个字符。 如果第一个字符相同,第二个字符不同,则只需要比较两个字符。 在你快完成之前,你不要比较整个单词。
我建议你实施 TRIE instead of implementing binary search algorithm. For example: each letter will be node of TRIE. The time complexity to build TRIE is O(W*L). W is number of word. L is average length of the word. When you find the word from TRIE 它需要 O(L).
您应该使用 Trie ADT
以获得良好的搜索操作性能。其中,只要用户输入'X',就会显示所有以'X'开头的标题。此功能与您在 Google、YouTube 或 Netflix 上看到的非常相似。显然,您可以对 Trie
的构造施加 more/fewer 约束,以随心所欲地塑造它。为什么 Trie 与数组?尝试更快。继续阅读以了解更多信息。
这里是Wikipedia article on Tries. An implementation of a Trie ADT in Java. An implementation of a T9 dictionary (like the good old days) in C.