Does priority_queue provide a predictable order? [duplicate] - c++

This question already has an answer here:
c++ ordered(stable) priority queue
(1 answer)
Closed 5 years ago.
wise guys
My question was like this:
I need to use priority_queue from std, everything works fine, until if there exists ties between my records, the order is no long consistent if I compile using clang compared to compiling on gcc.
my comparator function is simple:
bool comparator(const max_pair_t &lhs, const max_pair_t &rhs) {
return lhs.pval < rhs.pval;
}
that's it.
Is there a way to resolve this problem?
PS: I printed out all the records using two binary excutables, and compared the order side by side, the order is different, but the tied records are in the neighboring area

std::priority_queue gives no guarantees about sort stability. If you need sort stability, you'll have to provide it yourself, e.g. by storing a progressively increasing or decreasing value (doesn't really matter which, it just changes the direction of the fallback comparison) that is used when the primary comparison key is equal, and stripping it off when you pop off the queue.

Related

Which datastructure to use for finding an element [duplicate]

This question already has answers here:
How can I efficiently select a Standard Library container in C++11?
(4 answers)
Closed 4 years ago.
I have several items saved in a list. I would like to add items that have already been processed to a datastructure (this makes sense in my case even though you might wonder why). When processing the next item from the list I first want to make sure if it has been processed before so lets say something like this:
if(element_is_in_datastructure(current_element)) {
do this
}
else
{
do that
add_element_to_datastructure(current_element)
}
My question is, what is the ideal datastructure where checking if the element is in it won't take too long. At the moment I don't have too many elements (max 30) which will be added to the datastructure, but this number might increase and I don't want to lose performance.
You can use a map e.g std::unordered_map to store your elements as keys.
Then just check their presence e.g
if(!yourMap.count(element))
{
// your element is not in the structure
}
This finding takes logarithmic time in the map's size to finish.

same code, different order if tie exists in priority_queue, using clang and gcc [duplicate]

This question already has an answer here:
c++ ordered(stable) priority queue
(1 answer)
Closed 5 years ago.
wise guys
My question was like this:
I need to use priority_queue from std, everything works fine, until if there exists ties between my records, the order is no long consistent if I compile using clang compared to compiling on gcc.
my comparator function is simple:
bool comparator(const max_pair_t &lhs, const max_pair_t &rhs) {
return lhs.pval < rhs.pval;
}
that's it.
Is there a way to resolve this problem?
PS: I printed out all the records using two binary excutables, and compared the order side by side, the order is different, but the tied records are in the neighboring area
std::priority_queue gives no guarantees about sort stability. If you need sort stability, you'll have to provide it yourself, e.g. by storing a progressively increasing or decreasing value (doesn't really matter which, it just changes the direction of the fallback comparison) that is used when the primary comparison key is equal, and stripping it off when you pop off the queue.

std::map key no match for operator< [duplicate]

This question already has answers here:
How can I use std::maps with user-defined types as key?
(8 answers)
Closed 8 years ago.
I'm having quite a hard time trying to debug my little piece of code:
std::map<glm::ivec3,int> myMap;
glm::ivec3 myVec(3, 3, 3);
myMap.find(myVec);
I get the following error:
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\stl_function.h|237|error: no match for 'operator<' in '__x < __y'
Does that mean I can't check whether a glm::ivec3 is smaller than another?
I think that because a stl::map is ordered, the compiler wants to check which pair comes first. I tried to make the key a pointer and it worked.
Isn't there a way to keep the key a value instead of a pointer? This makes me ask another question: how can compare with a greater than operation something that cannot be compared or that is slow to be compared?
Thank you! :)
You can implement a comparison function:
bool operator<(const glm::ivec& lhs, const glm::ivec& rhs)
{
return lhs.x < rhs.x ||
lhs.x == rhs.x && (lhs.y < rhs.y || lhs.y == rhs.y && lhs.z < rhs.z);
}
(change .x, .y, .z to [0], [1], [2] / .first(), .second(), .third() etc as necessary.
how can compare with a greater than operation something that cannot be compared or that is slow to be compared?
Your pointer hack isn't uncommon but isn't always useful and has to be done with care - specifically, if someone comes along to search in the map and wants to find an existing element, they need a pointer to the same existing object that was earlier stored in the map. Or, choose some arbitrary ordering even if it makes no particular sense in the real world - as long as it's consistent.
If a comparison is just slow, you can potentially do things like compare a hash value first then fall back on the slower comparison for rare collisions (or if your hash is long/strong enough, return false on the assumption they're equal).
I'm not familiar with glm, but mathematically this doesn't surprise me as vectors don't have a natural ordering; I.e. What would it mean u < v when the two can be at any location in a 3d space. When you used pointers, it was using address ordering, often isn't a good idea as the addresses have nothing to do with the "values" of the keys. You can't really order on magnitude since you can end up with two completely different vectors being equal. If it is important to have an order you could order them lexicographically, comparing one dimension, then the next, etc. but you might want to consider an unordered_map (a hash table) unless there is some need for an ordering in your problem.
Here is a link that discusses the Java hashCode() function with some discussion of various approaches to hashing for compound objects.
http://www.javamex.com/tutorials/collections/hash_function_guidelines.shtml
For a class that has three ints as it's state, I'd probably do (((x*p)+y)*p)+z where p Is a small prime, say 31. (There are many variations on this and much more complex has functions depending on the structure of the data, etc.)
Here are some more links from SO on C++ hashing.
unordered_map hash function c++
C++ unordered_map using a custom class type as the key

std::bitset - how to iterate "set" (or "not set") bits? [duplicate]

This question already has answers here:
Efficient way of iterating over true bits in std::bitset?
(7 answers)
Closed 8 years ago.
I'm using bitset in my code:
std::bitset<MAX_INSTRUMENTS_NUMBER_IN_SYSTEM> updatedInstruments;
Often I need to iterate only values that "set" (or "not set"), this is how I do that:
for (int instrumentId = 0; instrumentId < MAX_INSTRUMENTS_NUMBER_IN_SYSTEM; instrumentId++) {
if (!updatedInstruments[instrumentId]) {
continue;
}
// work
}
Can this iteration be improved to be more readable and possibly faster?
I don't think you can exploit the contiguity of set bits in your code using std::bitset: the interface doesn't provide anything to help in this task, and there's no legal way to access the underlying storage and work directly with it.1
If instead you can afford to change container, you can find several better alternatives. Here for example is a bitset-like structure that provides "enumerators" for active bits (it seems mostly like working with spans on images), and in the duplicate I linked above there are several other suggestions for data structures more specialized for this use case.
Previously I supposed that iterators might have yielded some performance advantage, but turns out std::bitset doesn't have iterators :-o Also, a similar test performed on std::vector<bool> (which should pack bits more or less the same way) gave a ~2x slowdown using iterators both with g++ and clang++.

Updateable Priority Queue

Is there anything built into the C++ Standard Library that allows me to work in a priority queue/heap like data structure (i.e., can always pop the highest value from the list, can define how the highest value is determined for custom classes, etc.) but allows me to update the keys in the heap? I'm dealing with fairly simple data, pairs to be exact, but I need to be able to update the value of a given key within the heap easily for my algorithm to function. WHat is the best way to achieve this in C++?
Binary heaps (which are how priority queues are implemented in the C++ standard library) do not support arbitrary update-key operations. A common method if updates are infrequent is to extrinsically flag the original item as invalid, and reinsert the value with the new key; when an invalid value is popped, it is ignored.
The alternative is using a different PQ implementation which does support update-key, such as a binomial heap. Binomial heaps have the particular advantage of being manipulated by swinging pointers, instead of moving values. This streamlines the task of implementing operations like update-key and delete.
I'm not sure what you're take on Boost is, but I always consider a kind of almost standard library (some boost functionality has even ended up in standard library). In any case, if you're ok with using boost, then Boost.Heap provides a priority queue with updatable priority.
Like most boost libraries, it's header-only, so there's no linker hassles to go through and it won't make your build system any more complex. You can just #include it and use it.
I don't have the ability to comment on your question, but here is my understanding.
Your mentioned pairs, and it sounds like you need the ability to change the priority from some function of your first element of the pair to your second element.
That is, you want to initially use FirstComparator below, but then switch to SecondComparator.
typedef std::pair<X, Y> MyPair;
struct FirstComparator
{
bool operator() (const MyPair& left, const MyPair& right)
{
return left.first < right.first;
}
}
struct SecondComparator
{
bool operator() (const MyPair& left, const MyPair& right)
{
return left.second < right.second;
}
}
Because std::priority_queue is a template that includes a sorting criterion (as your question mentioned), you can create a second container of a different type. (I wrote less-than comparisons, so we have a min-heap.)
You will need to transfer the members into it.
std::priority_queue<MyPair, std::vector<MyPair>, FirstComparator> firstQueue;
// Populate and use firstQueue
// Now create an initially-empty queue sorting according to other criterion,
// and copy elements in.
std::priority_queue<MyPair, std::vector<MyPair>, SecondComparator> secondQueue;
// Use 'push' instead of 'emplace' for pre-C++11 code
while (! firstQueue.empty())
secondQueue.emplace(firstQueue.pop());
// Use secondQueue
An alternative approach is to use a single std::vector, and resort it with std::sort using different sorting criteria. C++11 allows you to create named or anonymous lambda functions for establishing such sorting criteria on-the-fly.
Since your question specifically involved priority queues, I won't get into that unless you're specifically interested.