线性搜索和二分搜索之间的权衡

Trade off between Linear and Binary Search

我有一个要在可变长度数据集中搜索的元素列表。我尝试过二进制搜索,但我发现当 objective 搜索元素列表时它并不总是有效。

我做了以下研究并得出结论,如果要搜索的元素数量少于数据的 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


    }

在代码中我重新调整了索引而不是值,因为我需要在调用函数中使用索引。如果 i=-1,调用函数将值重置为之前的 i,并使用要搜索的新元素再次调用该函数。

在您的问题中,您正在寻找 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(日志(M)*日志(N))。不清楚,欢迎评论!

但是 here is a test code - 我稍微修改了您的代码,但没有改变其功能。

如果您有 M=100000 和 N=1000000,"M binary search approach" 需要大约 1.8M 次迭代,这比线性扫描 N 值所需的 1M 次要多。但按照我的建议,它只需要 272K 次迭代。

即使M值非常"collapsed"(例如,它们是连续的),并且线性搜索处于最佳状态(100K迭代就足以得到它们,请参阅评论在代码中),该算法执行得非常好。