C++ 以相反的顺序获取'std::priority_queue'元素?

C++ 以相反的顺序获取'std::priority_queue'元素?,c++,priority-queue,stl-algorithm,knn,C++,Priority Queue,Stl Algorithm,Knn,我已经编写了一些K-最近邻查询方法,它们构建了一个距离给定查询点最近的点列表。为了维护这个邻居列表,我使用std::priority\u队列,这样顶层元素就是查询点最远的邻居。通过这种方式,我知道我是否应该推送当前正在检查的新元素(如果距离小于当前最远的邻居),并且当我的优先级队列包含超过K个元素时,可以弹出()最远的元素 到目前为止,一切顺利。但是,当我输出元素时,我希望从最近到最远的顺序排列它们。目前,我只需从优先级队列中弹出所有元素,并将它们放在输出容器中(通过迭代器),这将产生从最远到最

我已经编写了一些K-最近邻查询方法,它们构建了一个距离给定查询点最近的点列表。为了维护这个邻居列表,我使用
std::priority\u队列
,这样顶层元素就是查询点最远的邻居。通过这种方式,我知道我是否应该推送当前正在检查的新元素(如果距离小于当前最远的邻居),并且当我的优先级队列包含超过K个元素时,可以弹出()最远的元素

到目前为止,一切顺利。但是,当我输出元素时,我希望从最近到最远的顺序排列它们。目前,我只需从优先级队列中弹出所有元素,并将它们放在输出容器中(通过迭代器),这将产生从最远到最近的点序列,因此,我在输出迭代器范围内调用
std::reverse

作为一个简单的例子,这里有一个使用优先级队列的线性搜索(显然,我使用的实际最近邻查询方法要复杂得多):

模板
内联
输出迭代器最小距离线性搜索(前向迭代器优先,
ForwardIterator last,
首先输出计数器输出_,
GetDistanceFunction距离,
比较函数比较,
标准::大小\u t最大\u邻居=1,
距离值半径=标准::数值限制::无限(){
如果(第一个==最后一个)
首先返回输出_;
typedef std::priority_队列,
详细信息::首先比较\u对>优先队列;
PriorityQueue output_queue=PriorityQueue(详细信息::首先比较_对(比较));
for(;first!=last;++first){
距离值d=距离(*第一);
如果(!比较(d,半径))
继续;
输出_queue.push(std::pair(d,first));
while(output_queue.size()>max_邻居)
输出_queue.pop();
if(输出队列.size()=最大邻居)
radius=首先输出队列.top();
};
Outputierator it=首先输出;
而(!output_queue.empty()){
*it=*(output_queue.top().second);
输出_queue.pop();++它;
};
std::反向(首先输出,it);
归还它;
};
除了一件事之外,上面的一切都很好:它要求输出迭代器类型是双向的,并且本质上指向预先分配的容器。现在,这种将输出存储在某个输出迭代器指定的范围内的做法也是很好的标准做法(例如,
std::copy
和其他STL算法就是很好的例子)。然而,在本例中,我希望只需要一个前向输出迭代器类型,这将使使用后向插入器迭代器成为可能,就像为STL容器和iostreams提供的迭代器一样

因此,这归结为在将优先级队列的内容转储到输出迭代器之前反转优先级队列。所以,这些是我能想到的更好的选择:

  • 创建一个
    std::vector
    ,转储其中的优先级队列内容,并使用向量上的反向迭代器将元素转储到输出迭代器中

  • std::priority_队列
    替换为已排序的容器(例如
    std::multimap
    ),然后使用适当的遍历顺序将内容转储到输出迭代器中

还有其他合理的选择吗

我以前在这个算法和其他算法的一个实现中使用了
std::multimap
,这是我上面的第二个选项。然而,当我切换到
std::priority_queue
时,性能得到了显著提高。因此,我不想使用第二个选项,因为使用优先级队列来维护邻居列表似乎比依赖排序数组要好得多。顺便说一句,我还尝试了一个
std::vector
,我使用
std::inplace\u merge
对其进行排序,它比multimap好,但与优先级队列不匹配

至于第一个选项,这是我目前最好的选择,对我来说,必须进行双重数据传输(队列->向量->输出)似乎是浪费。我只是倾向于认为必须有一个更简单的方法来做到这一点。。。我缺少的东西


在这个应用程序中,第一个选项确实没有那么糟糕(考虑到它前面的算法的复杂性),但是如果有一个技巧可以避免这种双重内存传输,我想知道它。

一个肮脏的想法,尽管它保证会起作用,那就是:

std::priority_queue<int, std::vector<int>, std::less<int> > queue;
queue.push(3);
queue.push(5);
queue.push(9);
queue.push(2);

// Prints in reverse order.
int* front = const_cast<int*>(&queue.top());
int* back = const_cast<int*>(front + queue.size());
std::sort(front, back);
while (front < back) {
    printf("%i ", *front);
    ++front;
}
std::优先级队列;
排队推送(3);
排队推送(5);
排队推送(9);
排队推送(2);
//按相反顺序打印。
int*front=const_cast(&queue.top());
int*back=const_cast(front+queue.size());
标准::排序(前、后);
while(前<后){
printf(“%i”,*正面);
++前线;
}
请注意,就地排序可能会中断队列。

问题已解决

我真是个白痴。。。我知道我错过了一些明显的东西。在本例中,使用
std::sort_heap()
函数。甚至还有一个例子可以完全满足我的需要(而且由于
std::priority\u queue
只是根据随机访问容器和堆函数(pop\u heap、push\u heap、make\u heap)实现的,因此直接使用这些函数代替
std::priority\u queue
类并没有实际的区别)。我不知道我怎么会错过这个


无论如何,我希望这能帮助有同样问题的人。

为什么不在声明中指定相反的比较函数:

#include <iostream>
#include <queue>
#include <vector>
#include <functional>

int main() {
    std::priority_queue<int, std::vector<int>, std::greater<int> > pq;
    pq.push(1);
    pq.push(10);
    pq.push(15);
    std::cout << pq.top() << std::endl;
}
#include <iostream> #include <queue> #include <vector> #include <functional> int main() { std::priority_queue<int, std::vector<int>, std::greater<int> > pq; pq.push(1); pq.push(10); pq.push(15); std::cout << pq.top() << std::endl; }