我有一个可变长度数据集中要搜索的元素列表。我尝试过二进制搜索,但发现目标是搜索元素列表时并不总是很有效。
我进行了以下研究,并得出结论:如果要搜索的元素数量少于数据的5%,则二进制搜索是有效的,否则线性搜索会更好。
下面是详细信息
元素数:100000
要搜索的元素数:5000
迭代次数(二进制搜索)=
log2 (N) x SearchCount=log2 (100000) x 5000=83048
与线性搜索相比,搜索元素数量的进一步增加导致更多的迭代。
对此有何想法?
仅当要搜索的元素数小于5%时,我才调用以下函数。
private int SearchIndex(ref List<long> entitylist, ref long[] DataList, int i, int len, ref int listcount)
{
int Start = i;
int End = len-1;
int mid;
while (Start <= End)
{
mid = (Start + End) / 2;
long target = DataList[mid];
if (target == entitylist[listcount])
{
i = mid;
listcount++;
return i;
}
else
{
if (target < entitylist[listcount])
{
Start = mid + 1;
}
if (target > entitylist[listcount])
{
End = mid - 1;
}
}
}
listcount++;
return -1; //if the element in the list is not in the dataset
}
在代码中,我重新调整索引而不是值,因为我需要在调用函数中使用Index。如果i = -1,则调用函数会将值重置为上一个i,然后使用新元素再次调用该函数以进行搜索。
答案 0 :(得分:1)
在您的问题中,您正在寻找N个长数组中的M个值,N> M,但是M可能会很大。
通常,这可以通过M个独立的二进制搜索来实现(甚至可以稍微优化一下以以前的结果为起点):您将转到O(M * log(N))。
但是,利用M个值也被排序的事实,您可以通过线性搜索一次性找到所有它们。在这种情况下,您将遇到问题O(N)。实际上,这比M大的O(M * log(N))好。
但是您还有第三个选择:由于对M个值进行了排序,因此也对M个值进行了二进制分割,并且每次找到它时,都可以将后续搜索限制在找到的索引左右两侧的范围内。
第一次查询是在所有N个值上,第二次是在(平均)N / 2上,而不是在N / 4数据上是4个,....我认为这个标度为O(log(M) * log(N))。不确定,欢迎发表评论!
但是here is a test code-我对您的代码做了些微修改,但未更改其功能。
如果您有M = 100000和N = 1000000,则“ M二进制搜索方法”大约需要进行180万次迭代,这比线性扫描N个值所需的1M迭代次数还要多。但是根据我的建议,它仅需要272K迭代。
即使M值非常“折叠”(例如,它们是连续的),并且线性搜索处于最佳状态(100K迭代就足以获取所有值,请参见代码中的注释) ,该算法的效果很好。