我有以下课程:
struct EdgeExtended {
int neighborNodeId;
int weight;
int arrayPointer;
bool isCrossEdge;
};
我希望有一个这样的对象的向量,通过neighborNodeId对它进行排序。然后我想搜索特定的neighborNodeId并通过二进制搜索返回对向量中找到的对象的引用。以前我用过地图,所以就是这样:
map<int, EdgeExtended> neighbours;
.....
auto it = neighbours.find(dnodeId);
if (it != neighbours.end()) {
edgeMap = it->second;
}
而不是
map<int, EdgeExtended> neighbours;
我想要
vector<EdgeExtended> neighbours;
并保留尽可能多的旧代码。
我想测量矢量是否比地图快,因为我正在构建数千个矢量(或地图),每个矢量(地图)相对较小(~10个项目)。我不知道如何a)通过neighborNodeId对对象进行排序,以及b)如何使用二进制搜索来搜索类的特定成员(neighborNodeId)。抱歉,这个菜鸟问题。我指望你的帮助。
答案 0 :(得分:9)
您需要一个自定义比较器功能,该功能需要两个EdgeExtended
个对象并比较您感兴趣的字段,并且可以作为第三个或第四个传递给sort
和binary_search
论证,分别。
可以使用lambda函数方便地完成:
auto Comp = [](const EdgeExtended& e1, const EdgeExtended& e2)
{
return e1.neighborNodeId < e2.neighborNodeId;
};
如果您坚持使用C ++ 11之前的版本,请编写一个重载operator()
的类:
struct Comp {
bool operator()(const EdgeExtended& e1, const EdgeExtended& e2) const
{
return e1.neighborNodeId < e2.neighborNodeId;
}
};
答案 1 :(得分:3)
根据jrok的回答,如果你经常遇到类似的问题,使用类的任何成员的可重复使用的模板化比较器非常方便。
template<class T, class U>
class CompareByMember {
U (T::*mem); // ugly syntax for member pointer of type U in class T
public:
CompareByMember(U (T::*mem)) : mem(mem) {}
bool operator()(const T &a, const T &b) {
return (a.*mem) < (b.*mem); // ugly syntax for member pointer access
}
};
正如您所看到的,指向类成员的指针的语法非常奇怪,但是一旦包含在这个仿函数中,您就不必关心它了。剩下的一个“问题”是每次要使用此仿函数时都必须编写模板参数<T, U>
。但是使用类型推导这个问题就解决了,引入了一个小帮助函数(注意它的名字是小写的):
template<class T, class U>
CompareByMember<T,U> compareByMember(U (T::*mem)) {
return CompareByMember<T,U>(mem);
}
这导致客户端代码如下:
std::vector<EdgeExtended> v = ...;
std::sort(v.begin(), v.end(), compareByMember(&EdgeExtended::neighborNodeId));
对于成员函数,可以使用唯一略有不同的成员函数指针语法编写类似的模板化仿函数。您还可以在函子中重载调用操作符以接受T
的原始指针以及T*
周围的任何智能指针(再次使用模板)。