C++11 优先级队列上的二进制搜索(高效插入和搜索大量字符串)

C++11 优先级队列上的二进制搜索(高效插入和搜索大量字符串),c++11,priority-queue,C++11,Priority Queue,我面临的问题是持有大量字符串(~50k)。每个字符串描述一个已经考虑过的场景。因此,当新场景出现时,如果其描述已经在列表中,则该场景将被丢弃 我在想,显而易见的选择是使用字符串的优先级队列来执行二进制搜索。(对数插入、对数查找) 对吧? < >我无法找到一个使用标准C++库的方法。 特别是,优先级队列似乎没有.begin().end() 为二进制搜索()函数指定的方法 我不能使用标准库优先级队列+二进制搜索吗? 那么,还有什么用呢 谢谢 编辑1。 最后,经过几次测试,我可以确认这个问题的最佳选择

我面临的问题是持有大量字符串(~50k)。每个字符串描述一个已经考虑过的场景。因此,当新场景出现时,如果其描述已经在列表中,则该场景将被丢弃

我在想,显而易见的选择是使用字符串的优先级队列来执行二进制搜索。(对数插入、对数查找)

对吧?

< >我无法找到一个使用标准C++库的方法。 特别是,优先级队列似乎没有.begin().end() 为二进制搜索()函数指定的方法

我不能使用标准库优先级队列+二进制搜索吗? 那么,还有什么用呢

谢谢

编辑1。 最后,经过几次测试,我可以确认这个问题的最佳选择(优于其他问题)是使用集合及其find方法。这是:

set<string> consideredOptions; 
...
string newDescription = ....;
if ( consideredOptions.find(newDescription) == consideredOptions.end() ) {
  consideredOptions.insert(newDescription);
}
设置考虑因素;
...
字符串newDescription=。。。。;
if(consideredOptions.find(newDescription)==consideredOptions.end()){
考虑事项。插入(新说明);
}
编辑2。 优先级队列有一个名为c的受保护成员,代表项目列表。然后,使用.begin()和.end()方法很容易派生一个新类

class MyQueue:public std::priority\u队列{
公众:
bool包含(const std::string&what)const{
返回std::find(c.begin(),c.end(),what)!=c.end();
}
};
< >我无法找到一个使用标准C++库的方法。

您不需要队列,只需要一个可以高效插入和查找的集合。使用
std::无序集
。它具有恒定的插入和查找时间

当事情到达队列的“前端”时,您需要处理它们(通常将它们从队列中移除)时,使用队列。根据你所描述的,你不需要那个。你只关心物品是否在收藏中,而不关心它们是否在前面

使用
std::set
std::unordered\u set
您甚至不需要费心查找,只需插入每个字符串即可。如果它已经在容器中,那么返回值将告诉您插入失败。如果它不在容器中,返回值会告诉您它不在容器中,但会在相同的操作中添加它,这是查找然后插入的两倍

unordered_set<string> consideredOptions; 
...
string newDescription = ....;
if ( consideredOptions.insert(newDescription).second ) {
  // newDescription was not in the set (but is now)
}
else {
  // newDescription was already considered
}
unordered\u集考虑的选项;
...
字符串newDescription=。。。。;
if(consideredOptions.insert(newDescription.second){
//newDescription不在集合中(但现在已存在)
}
否则{
//新的描述已经被考虑过了
}

为什么您认为优先级队列会有用,而不是排序的
向量
,或
集合
,或
无序集合
?(您可以从
priority\u queue
派生您自己的类型,该队列将有权访问公开开始/结束迭代器的受保护
c
成员…但不要这样做)。实际上,听起来像
map
无序\u map
是您想要的(仔细想想可能只是
)@Jonathan我考虑了priority_队列,这样就不会每次在向量上插入一个新字符串时都执行sort()。优先级队列具有日志插入成本。如果对pq进行排序,则要查找的二进制搜索是最佳的(日志成本)。集也有对数插入,并且在查找时自动执行二进制搜索。你把事情复杂化了,而这不是优先级队列的作用。标准库中有大量的容器,它们可以完全满足您的需要,优先级队列不是其中之一。@JonathanWakely是的,可能我把它复杂化了。然后,我必须用一个集合来替换pq。谢谢。你确定在“无序”集合中搜索是最优的(日志成本很高)吗?这取决于你有多少冲突,以及容器的负载因子,但是使用一个好的哈希函数比对数更好。(旁白:为什么你认为搜索和插入不同?他们必须做同样的事情。)@JonathatWakely谢谢。比较集合与无序集合,后者优于前者。经过多次尝试,我的问题的正确选择不是无序集合。事实上,这是不正确的:它无法在集合中找到正字符串。正确的选择是set+它的find方法(而不是函数binary\u search)。那么您使用无序的\u set是错误的,如果它在集合中找不到字符串,那么在实现中将是一个严重的错误,我怀疑您是否发现了这样的错误(现在其他人可能已经注意到了)。检查元素是否存在的最简单方法不是
find
,而是
count
。但请阅读我在上面写的内容,不必费心查找,只需插入并查看它是否有效。如果您真的关心性能,那么执行查找+插入是愚蠢的,因为它所做的工作是所需工作的两倍。
unordered_set<string> consideredOptions; 
...
string newDescription = ....;
if ( consideredOptions.insert(newDescription).second ) {
  // newDescription was not in the set (but is now)
}
else {
  // newDescription was already considered
}