C++ 设置insert进行奇怪的比较
我无法解释std::set在插入新元素时进行的比较次数。以下是一个例子: 对于此代码C++ 设置insert进行奇怪的比较,c++,stl,set,comparator,C++,Stl,Set,Comparator,我无法解释std::set在插入新元素时进行的比较次数。以下是一个例子: 对于此代码 struct A { int i = 0; bool operator()(int a, int b) { ++i; return a < b; } }; int main() { A a; set<int, A> s1(a); s1.insert(1); cout <&
struct A {
int i = 0;
bool operator()(int a, int b)
{
++i;
return a < b;
}
};
int main()
{
A a;
set<int, A> s1(a);
s1.insert(1);
cout << s1.key_comp().i << endl;
s1.insert(2);
cout << s1.key_comp().i << endl;
}
为什么插入第二个元素需要3次比较?o_o这是使用红黑树实现
std::set
的一个副作用,与标准二叉树相比,它最初需要更多的比较。我不知道具体情况,因为它们取决于std::set
实现,但是确定两个项的相等性需要两次比较,因为它基于这样一个事实,not(x
意味着x==y
根据树的优化方式,您可能需要进行第一次比较以确定它应该向左还是向右,然后进行两次比较以检查它是否相等
本标准没有要求比较次数为O(对数N),其中N是
集合中已存在的项数
。恒定因素是实施质量问题。乍一看似乎有些奇怪。你使用的C++标准是什么?哪个stl?调试版本和非调试版本之间是否一致?我增加了测试用例以进行更多的比较,它产生了[0,3,4,4,5,5,6,6,6]
@Angew是的,不幸的是。对于调试和发布@ BaseSeBi的结果,我使用C++ 11,这里是我的编译器的细节:Apple LLVM版本4.2(CLAN-425.0.28)(基于LLVM 3.2Svn)目标:X86Y64-APPL-DARWIN 114.2线程模型:PosiXi也期待两个非相等测试的比较,但是其中一个测试也暗示了元素应该向右还是向左的结果,所以我不明白你关于第三个的观点comparison@IssamT.:这是因为您假设左/右检查的结果被重新用于相等性测试。正如我的第二段所指出的,不一定如此。@matthieum:我明白你的意思了。但我通常认为stl库是以一种非常智能的方式实现的,因此如果实现不重用以前完成的结果,那就很奇怪了comparison@IssamT.:这是一个相当不成熟的优化。当一棵树有N个级别时,最多有N个比较来定位该位置,然后有2个比较用于相等。N+1(优化)和N+2(非优化)之间的差异并不是很大。当我思考它时,它确实是有意义的:记住上次比较的结果会给每个操作增加开销。对于一棵大树,这些可能会超过你所看到的单个额外的比较。最重要的是,你会得到循环复杂度的增加。你能进一步说明为什么红黑树需要更多的前期比较吗。我对这种结构不够熟悉,无法理解为什么它是一种需求。@MatthieuM。这两个额外的比较源于这样一个事实,即红黑树节点总是有两片叶子,因此第一次插入技术上会添加根和两片(null)叶子,当添加第二个元素时,它必须与两片叶子进行比较,因为与第一片叶子进行比较的任何一片叶子都会返回null。至少这是我有根据的猜测,因为我自己并不太熟悉。
0
3