C++ 在集合中使用emplace_hint的用例是什么?
在集合中使用emplace_hint的用例是什么?我给出了一个提示(在下面的程序中是s.begin()),但是,emplace_提示似乎没有注意到它。程序-C++ 在集合中使用emplace_hint的用例是什么?,c++,c++11,C++,C++11,在集合中使用emplace_hint的用例是什么?我给出了一个提示(在下面的程序中是s.begin()),但是,emplace_提示似乎没有注意到它。程序- #include <iostream> #include <string> #include <set> using namespace std; void show(set<string>& s) { set<string>::iterator it = s.
#include <iostream>
#include <string>
#include <set>
using namespace std;
void show(set<string>& s) {
set<string>::iterator it = s.begin();
cout << "<" << *it++;
for (; it != s.end(); it++)
cout << ", " << *it;
cout << ">" << endl;
}
set<string>::iterator myEmplaceHint(set<string>::iterator hint_it, set<string> &s, string e) {
set<string>::iterator ret_it, tmp_it;
cout << "hint_it :" << *hint_it << endl;
ret_it = s.emplace_hint(hint_it, e);
return ret_it;
}
int main(int argc, char *argv[]){
set <string> s = { "alpha", "beta", "gamma", "delta" };
show(s);
string str("epsilon"), retVal;
retVal = *myEmplaceHint(s.begin(), s, str);
cout << "retVal :" << retVal << endl;
show(s);
return 0;
}
$ make
g++ -g -Wall -o test test.cpp
$ ./test
<alpha, beta, delta, gamma>
hint_it :alpha
retVal :epsilon
<alpha, beta, delta, epsilon, gamma>
#包括
#包括
#包括
使用名称空间std;
无效显示(设置和设置){
set::iterator it=s.begin();
库特
std::set
始终按比较类型指定的顺序存储项目。这默认为std::less
,这意味着默认情况下项目将始终为升序。无论您提示什么,集合都保证维护顺序
emplace_提示旨在避免在您已经知道项目应插入的位置时再次搜索集合
一个非常简单的例子:
#include <set>
#include <cassert>
void ensure_present(std::set<int>& s, int v)
{
// finding the upper bound is O(logN)
auto i = s.upper_bound(v);
if (i == std::end(s) || *i != v) {
// this would be inefficient since we'd be performing another redundant
// O(logN) search for the insertion point
// s.emplace(v);
// since we already have the position close to were it should go, we
// can avoid another search
s.emplace_hint(i, v);
}
}
#包括
#包括
无效确保存在(标准::设置与s,int v)
{
//求上界是O(logN)
自动i=s.上界(v);
如果(i==std::end(s)| |*i!=v){
//这将是低效的,因为我们将执行另一个冗余
//O(logN)搜索插入点
//s.emplace(v);
//既然我们已经有了接近它应该离开的位置,我们
//可以避免再次搜索
s、 安放提示(i,v);
}
}
良好的暗示有助于提高性能。起初,我在这里写了一条关于性能改进程度的错误评论。但仔细想想,无论如何,复杂性大约为O(n log n),所以我们讨论的是一个常数因子,它取决于数据和实现。请注意,如果您不一定需要按排序顺序重复列出项目,则无序集为您提供了插入n个项目的O(n)复杂性。@cheers sandhth.-Alf您是否愿意就O(nlogn)复杂性进行说明?我们不是得到了O(1)如果我们提供了正确的提示?由于集合
必须能够生成一个已排序的项目序列,因此它必须使用一个数据结构来对项目进行排序。实际上,这意味着某种平衡树。对于已排序的项目,完美的提示将排除所有现有的树,因为最后添加的节点必须是rightmost,但添加新节点会涉及(我认为这将在大约一半的情况下)树的重新平衡。重新平衡是一个O(logn)操作。重复的(是的,我知道你问过set
,但实际上它们使用相同的数据结构;set只是一个只有一个键的映射,没有值)您可以在第二点中添加一个注释,大意是“允许实现忽略提示。”同意!在集合s={23,45,21,87,5,33,86,73}上;我尝试了it=s.find(87);s.emplace_hint(it,22);但它仍然在21之后插入。emplace_提示旨在避免在您已经知道项目应插入的位置时再次搜索集合。这是否意味着如果我们提供错误提示,将对性能产生影响?@OnkarNMahajan,这将由实现定义。实际上,您应该预期的最坏影响是提示是ignored,搜索从树的根开始,即返回到O(logN)