- 尽管
std::priority_queue 的序列容器可以像std::stack 一样指定,但必须指定一个能够维护插入顺序的非关联容器,例如std::vector 或std::deque(使用随机访问迭代器)。
即使 std::set 可以在此处用于删除重复项,std::priority_queue 也不会像 std::set 或 std::map 那样返回是否已插入元素的指示符。
- 带有自定义比较器的普通
std::set 可以很好地工作,可以使用begin() 或rbegin() 和erase() 插入和删除元素。
- 另一种方法是在序列容器中手动维护自定义堆。这样做通常是为了避免由关联容器的链接结构或链接列表(如
std::set、std::map、std::list、std::forward_list、...)引起的内存碎片和某些性能损失:
- 另请注意,
std::heap* 算法可以保持特定于实现的顺序,因此不能期望产生与std::sort() 相同的结果。
#include <iostream>
#include <numeric>
#include <algorithm>
#include <vector>
#include <deque>
#include <cstdlib>
///@brief Internal insert function for ordered sequences
template<class SequenceContainer, typename Value, class Comparator>
inline typename std::pair<typename SequenceContainer::iterator, bool> heap_set_insert_(SequenceContainer& heap, const Value& value, Comparator comparator)
{
std::pair<typename SequenceContainer::iterator, bool> result(std::lower_bound(heap.begin(), heap.end(), value, comparator), false);
if (!(result.first != heap.end() && !comparator(value, *result.first)))
{
result.first = heap.insert(result.first, value);
result.second = true;
}
return result;
}
/**
* @brief insert function for an ordered vector, works like std::set::insert(const value_type&)
* @param heap The supplied container must already be sorted using the specified comparator
*/
template<typename T, class Allocator, class Comparator = std::less<T> >
inline typename std::pair<typename std::vector<T, Allocator>::iterator, bool> heap_set_insert(std::vector<T, Allocator>& heap, const T& value, Comparator comparator)
{
return heap_set_insert_<std::vector<T> >(heap, value, comparator);
}
/**
* @brief insert function for an ordered deque, works like std::set::insert(const value_type&)
* @param heap The supplied container must already be sorted using the specified comparator
*/
template<typename T, class Allocator, class Comparator = std::less<T> >
inline typename std::pair<typename std::deque<T, Allocator>::iterator, bool> heap_set_insert(std::deque<T, Allocator>& heap, const T& value, Comparator comparator)
{
return heap_set_insert_<std::deque<T> >(heap, value, comparator);
}
///@brief Prints all elements of any container as an array to a std::ostream: {[,elem]...}.
///@note Special container elements and std::pair<> may need additional ostream overloads
template<class Container>
inline std::ostream& print_container_(std::ostream& o, const Container& s)
{
o << '{';
for (typename Container::const_iterator it = s.begin(); it != s.end(); ++it)
{
if (it != s.begin())
o << ',';
o << *it;
}
o << '}';
return o;
}
///@brief Equality functor, derived from a set comparator (which may evaluate less/greater than).
template<typename SetComparator>
class SetAdjacencyComparator
{
public:
SetAdjacencyComparator(const SetComparator& setCmp = SetComparator()) :
setCmp(setCmp)
{
}
//Elements are equal, if neither is less/greater than the other
bool operator()(int a, int b)
{
return !setCmp(a, b) && !setCmp(b, a);
}
private:
SetComparator setCmp;
};
int main()
{
//May be a function pointer
//For a set (with unique values), use less/greater only!
typedef std::less<int> MyCompare;
MyCompare cmp;
std::cout << std::boolalpha;
{
std::deque<int> s
{ 7, 8, 3, 4, 9, 10, 1, 2, 6, 5 }; //(C++11)
//Initialize the custom heap using the one comparator, which is used for all subsequent operations
std::sort(s.begin(), s.end(), cmp);
print_container_(std::cout, s) << std::endl;
std::cout << "inserted: " << heap_set_insert(s, 3, cmp).second << std::endl;
std::cout << "inserted: " << heap_set_insert(s, 33, cmp).second << std::endl;
std::cout << "inserted: " << heap_set_insert(s, 11, cmp).second << std::endl;
print_container_(std::cout, s) << std::endl;
std::cout << "is_sorted() : " << std::is_sorted(s.begin(), s.end(), cmp) << std::endl;
std::cout << "unique : " << (std::adjacent_find(s.begin(), s.end(), SetAdjacencyComparator<MyCompare>(cmp)) == s.end()) << std::endl;
//^- In order for this check to work, the sequence must be sorted in such a way, that equal elements are adjacent
std::cout << "highest (top) : " << s.back() << std::endl;
std::cout << "lowest : " << s.front() << std::endl;
}
std::cout << std::noboolalpha;
return EXIT_SUCCESS;
}