C++ 为什么实现的二进制搜索比std::binary_search()慢得多?
在检测到std::upper_bound之前,我实现了自己版本的binarySearch,以确定所需元素的索引。该实现可以工作,但与线性搜索相比,我的binarySearch只快了一点点。我的实现和std库之间的因素随着搜索区域的增长而增加 为了快速进行自检,我在本文末尾插入了完整的代码。要快速浏览一下我的searchBinary实现:C++ 为什么实现的二进制搜索比std::binary_search()慢得多?,c++,performance,binary-search,C++,Performance,Binary Search,在检测到std::upper_bound之前,我实现了自己版本的binarySearch,以确定所需元素的索引。该实现可以工作,但与线性搜索相比,我的binarySearch只快了一点点。我的实现和std库之间的因素随着搜索区域的增长而增加 为了快速进行自检,我在本文末尾插入了完整的代码。要快速浏览一下我的searchBinary实现: template<typename T> T searchBinary(const std::vector<std::vector<T&
template<typename T> T searchBinary(const std::vector<std::vector<T> > vectorList, const std::vector<T> compareVector) {
long iteration = 0;
size_t leftIndex = 0;
size_t rightIndex = vectorList.size()-1;
size_t pos;
while (leftIndex <= rightIndex) {
iteration++;
pos = (leftIndex + rightIndex) / 2;
if (compareVector < vectorList[pos]) {
rightIndex = pos - 1;
} else if (compareVector > vectorList[pos]) {
leftIndex = pos + 1;
} else {
cout << "Match at binary search after " << iteration << " iterations.\n";
return pos;
}
}
cout << "No match at binary search after " << iteration << " iterations.\n";
return -1;
}
模板T searchBinary(常量std::向量向量向量列表,常量std::向量比较向量){
长迭代=0;
大小\u t leftIndex=0;
size\u t rightIndex=vectorList.size()-1;
尺寸和位置;
while(leftIndex向量列表[pos]){
leftIndex=pos+1;
}否则{
这个模板T searchBinary(const std::vector vectorList,const std::vector compareVector)
制作了一个输入向量的副本(当您通过值传递它时),它在时间上是线性的。所以您得到的结果实际上是预期的
顺便说一句,一个开玩笑的回答可能是,标准库是由相当优秀的开发人员编写的,预计它的性能很难超越
将函数原型更改为
模板T searchBinary(const std::vector&vectorList,const std::vector&compareVector){
i、 通过常量引用而不是通过值传递。这将避免两个向量副本
您可以使用单个条件测试进行重构,向量通过值传递给searchBinary
,因此将创建副本,这需要时间
如果您将签名更改为
template<typename T> T searchBinary(const std::vector<std::vector<T> >& vectorList, const std::vector<T>& compareVector)
模板T searchBinary(常量std::vector&vectorList、常量std::vector&compareVector)
它与std实现一样快:我没有时间仔细查看,但是您的searchBinary
创建了您传递的两个向量的副本,因此这将至少是一个瓶颈。因为许多人在算法标准化之前花了很长时间研究算法。-)您的项目2不仅仅是一个“微型”优化。这几乎是二的一个因素。除非我误解了,否则您仍然需要对正在排序的值进行<测试,同时对索引进行一些条件测试。但是取消对正在排序的值的>测试可以节省近一半的时间。然后在这段时间之后,您需要额外的测试,以查看leftIndex-1是否是您需要的项搜索(如果leftIndex初始化为1而不是0,则更安全、更快)。如果打印的迭代次数确实有趣,则整个想法都失败了。但我认为不是。你当然是对的。我已经改进了我的语言。如果你在回答中提供代码,我肯定会支持它。
#include <iostream>
#include <vector>
#include <sys/time.h>
#include <algorithm>
#include <string>
#include <stdio.h>
using namespace std;
template<typename T> T searchBinary(const std::vector<std::vector<T> > vectorList, const std::vector<T> compareVector) {
long iteration = 0;
size_t leftIndex = 0;
size_t rightIndex = vectorList.size()-1;
size_t pos;
while (leftIndex <= rightIndex) {
iteration++;
pos = (leftIndex + rightIndex) / 2;
if (compareVector < vectorList[pos]) {
rightIndex = pos - 1;
} else if (compareVector > vectorList[pos]) {
leftIndex = pos + 1;
} else {
cout << "Match at binary search after " << iteration << " iterations.\n";
return pos;
}
}
cout << "No match at binary search after " << iteration << " iterations.\n";
return -1;
}
size_t searchLinear(std::vector<std::vector<u_char> > vectorList, std::vector<u_char> compareVector) {
size_t vectorListSize = vectorList.size();
for (size_t i = 0; i < vectorListSize; i++) {
if (vectorList[i] == compareVector) {
return i;
}
}
return (size_t)-1;
}
void searchLinear_messure(std::vector<std::vector<u_char> > vectorList, std::vector<u_char> compareVector) {
struct timeval begin, end;
long seconds, useconds;
if (gettimeofday(&begin,(struct timezone *)0)) {
fprintf(stderr, "can not get time\n");
exit(1);
}
//search
cout << "\nPos: " << searchLinear(vectorList, compareVector) << endl;
if (gettimeofday(&end,(struct timezone *)0)) {
fprintf(stderr, "can not get time\n");
exit(1);
}
seconds = end.tv_sec - begin.tv_sec;
useconds = end.tv_usec - begin.tv_usec;
if(useconds < 0) {
useconds += 1000000;
seconds--;
}
printf("searchLinear(): %ld sec %ld usec\n\n", seconds, useconds);
return;
}
void searchBinaryStd_messure(std::vector<std::vector<u_char> > vectorList, std::vector<u_char> compareVector) {
struct timeval begin, end;
long seconds, useconds;
if (gettimeofday(&begin,(struct timezone *)0)) {
fprintf(stderr, "can not get time\n");
exit(1);
}
//search
cout << "found: " << std::binary_search(vectorList.begin(), vectorList.end(), compareVector) << endl;
if (gettimeofday(&end,(struct timezone *)0)) {
fprintf(stderr, "can not get time\n");
exit(1);
}
seconds = end.tv_sec - begin.tv_sec;
useconds = end.tv_usec - begin.tv_usec;
if(useconds < 0) {
useconds += 1000000;
seconds--;
}
printf("searchBinaryStd(): %ld sec %ld usec\n\n", seconds, useconds);
return;
}
void searchBinaryOwn_messure(std::vector<std::vector<u_char> > vectorList, std::vector<u_char> compareVector) {
struct timeval begin, end;
long seconds, useconds;
if (gettimeofday(&begin,(struct timezone *)0)) {
fprintf(stderr, "can not get time\n");
exit(1);
}
searchBinary(vectorList, compareVector);
if (gettimeofday(&end,(struct timezone *)0)) {
fprintf(stderr, "can not get time\n");
exit(1);
}
seconds = end.tv_sec - begin.tv_sec;
useconds = end.tv_usec - begin.tv_usec;
if(useconds < 0) {
useconds += 1000000;
seconds--;
}
printf("searchBinaryOwn(): %ld sec %ld usec\n\n", seconds, useconds);
return;
}
int main() {
std::vector<u_char> compareVector;
compareVector.clear();
compareVector.push_back(0xF8);
compareVector.push_back(0xD1);
compareVector.push_back(0x11);
compareVector.push_back(0xFF);
std::vector<std::vector<u_char> > vectorList;
vectorList.clear();
std::vector<u_char> temp;
for (unsigned int i = 0; i < ((unsigned int)-1); i++) {
if (i == 8000000) {
// if (i == 15000000) {
break;
}
temp.clear();
temp.push_back(0x11);
temp.push_back(0x22);
temp.push_back(0x33);
temp.push_back(0x44);
vectorList.push_back(temp);
}
vectorList[7999999] = compareVector;
cout << "Elements in vectorList: " << vectorList.size() << endl;
searchLinear_messure(vectorList, compareVector);
searchBinaryStd_messure(vectorList, compareVector);
searchBinaryOwn_messure(vectorList, compareVector);
return 0;
}
template<typename T> T searchBinary(const std::vector<std::vector<T> >& vectorList, const std::vector<T>& compareVector)