Is i have a priority queue with declaration
priority_queue<<Node>,vector<Node>,myComp> openQ
i am inserting node objects into it. but at some time i have to delete the element from it. (not to remove the top element)
Currently to delete it i am popping the element and putting it in array. if the top most element is desired then expect it i push other elements in array.
This is like linear search and delete. I know its not efficient and i am looking for some better ways
priority_queue class is designed for using as queue with priorities. And it designed to remove elements with pop function. If you want to get different behavior you should use different class. For instance, std::map.
If you're ready to manually control a consistence of the queue you may take a look on std::make_heap. It's easy to create a max-heap with it. But in this case you need to manually rebuild a queue each time you want to remove an element.
std::set are orderd and can erase elements by value. the underlying datastructure is a binary search tree, thats why its cheaper to erase elements by value.
a priority queue would have to linearly search through the queue, so its possible but just not very efficient, thats why they didnt include it.
Related
So I am looking for a data structure which needs a FIFO behaviour but should also have a quick look up time by value.
In my current code I have some data duplication. I use a std::unordered_set and std::queue for achieving the behaviour I want but there's probably a better way of achieving this that I'm not thinking of at the moment. I have a function that adds my new entry to both the set and the queue when a new entry comes up. To search if an entry exists in the queue I use find() in the set. Laslty, I have a timer that is set off after an insertion to the queue. After a minute I get the entry in the front of the queue with queue.front(), then I use this value to erase from the set, and finally I do a pop on the queue.
This all works as expected and gives me both the FIFO behaviour and the constant time complexity for the look up but I have data duplication and I was wondering if there is a data structure (maybe something form boost?) which does what I want without the duplication.
Data structure for FIFO behaviour and fast lookup by value
A solution is to use two containers: Store the elements in an unordered set for fast lookup, and upon insertion, store iterator to the element in a queue. When you pop the queue, erase the corresponding element from the set.
A more structured approach is to use a multi-index container. The standard library doesn't provide such, but boost does. More specifically, you could use a combination of hashed and sequence indices.
This answer is mostly concerning corner cases of the problem as presented
If you problem is a practical one, and you are able store the elements with a std::vector - and if you have less than in the ballpark of some ~10-100 elements in the queue, then you could just use:
std::queue<T, std::vector<T> > q;
That is a queue using vector as the underlying container. When you have that small number of elements (only 10-100) then using advanced lookup methods is not worth it.
You then only needs to check for duplicates when you pop the queue not on every insertion. Again, that might or might not be usefull depending on your specific case. I can imagine cases where this method is superior. Eg. a webserver serving pages that gets a lot of hits to just one or a few pages. Then it might be faster to just add say 100,000 elements to the vector and then go and remove the duplicates all in one go when popping.
How about defining your own data structure which can act as a BST (for lookups) and as a min heap which you can use to impose fifo?
class node {
public:
static int autoIncrement = 0;
int order; // this will be auto-incremented to impose FIFO
int data;
node* left_Bst;
node* right_Bst;
node* left_Heap;
node* right_Heap;
node() {
order = autoIncrement;
autoIncrement++;
}
}
By doing this you are basically creating two data structures sharing the same nodes. BST's partial order is imposed via data, and heap's can be maintained via order variable.
During an insertion you can traverse via BST pointers and insert your element if it doesn't exist already and also modify the heap pointers accordingly after insertion.
How i can access/search randomly in a priority queue?. for example, if have a priority queue like q={5,4,3,2,1} for example, i want to access 3rd value directly which is 3, i could not do this,is there any process to access randomly in priority queue?
Most priority queue implementations, including the C++ std::priority_queue type, don't support random access. The idea behind a priority queue is to sacrifice random access for fast access to the smallest element.
Depending on what you're trying to do, there are a number of other approaches you could use. If you always want access to the third element in the queue (and not any other arbitrary positions), it's probably fast enough to just dequeue two elements, cache them, then dequeue the value you want and put the other two elements back.
If you want access to the kth-smallest element at any point in time, where k is larger, one option is to store two different priority queues: a reverse-sorted priority queue that holds k elements (call it the left queue) and a regular priority queue holding the remaining n-k elements (call it the right queue). To get the kth-smallest element, dequeue from the left queue (giving back the kth-smallest element), then dequeue an element from the right and enqueue into the left to get it back up to k total elements. To do an enqueue, check if the number is less than the top of the left queue. If so, dequeue from the left queue, enqueue the removed element into the right queue, then enqueue the original element into the left. Otherwise, enqueue into the right. This guarantees O(log n) runtimes for each operation.
If you need true random access to a sorted sequence, consider using an order statistics tree. This is an augmented binary search tree that supports O(log n) access to elements by index. You can use this to build a priority queue - the minimum element is always at index 0. The catch (of course there's a catch) is that it's hard to find a good implementation of one and the constant factors hidden in the O(log n) terms are much higher than in a standard binary heap.
To add to the answer of #templatetypedef:
You cannot combine random access of elements with a priority queue, unless you use a very inefficient priority queue. Here's a few options, depending on what you need:
1- An inefficient priority queue would be a std::vector that you keep sorted. Pushing an element means finding where it should be inserted, and move all subsequent elements forward. Popping an element would be simply reading and deleting the last element (back and pop_back, these are efficient). Random access is efficient as well, of course.
2- You could use a std::multiset (or std::multimap) instead of a priority queue. It is a tree structure that keeps things sorted. You can insert instead of push, then read and remove the first (or last) element using a begin (or rbegin) iterator with erase. Insertion and finding the first/last element are log(n) operations. The data structure allows for reading all elements in order, though it doesn't give random access.
3- You could hack your own version of std::priority_queue using a std::vector and the std::push_heap and std::pop_heap algorithms (together with the push_back and pop_back methods of the std::vector). You'd get the same efficient priority queue, but also random access to all elements of the priority_queue. They are not sorted, all you know is that the first element in your array is the top priority element, and that the other elements are stored in a way that the heap property is satisfied. If you only occasionally want to read all elements in order, you can use the function std::sort_heap to sort all elements in your array by priority. The function std::make_heap will return your array to its heap status.
Note that std::priority_queue uses a std::vector by default to store its data. It might be possible to reinterpret_cast the std::priority_queue to a std::vector, so you get random access to the other elements in the queue. But if it works on your implementation of the standard library, it might not on others, or on future versions of the same library, so I don't recommend you do this! It's safer to create your own heap class using the algorithms in the standard library as per #3 above.
I have 2 vectors, y and T initially of the same size, and they need to stay separated like this. I do a loop until T is empty and every time it loops, the first element of T is used for an algorithm and then erased from the vector T and pushed into vector S (which is empty at first). Every loop, some values in vector y will change and I need to sort them. My problem is: when I sort y, if y[2] and y[3] swap, I need to swap the elements in T that were at [2] and [3] BEFORE the first loop!
I know this seems weird but this is for a Dijkstra algorithm for my Graph project. I understand if it's not clear and I'll try to clarify if you need it. Any advice will be very helpful for me! Thank you!
If I follow you correctly, T is really a FIFO queue. The first element in it each iteration is being 'popped off the front' and placed elsewhere.
Should you be doing this and want at any time to know an ordering of T which includes the elements that were popped off, perhaps you could not remove them from T at all. Just have an iterator or pointer to the next node to be processed.
That node could either be copied to S, or perhaps S would just contain pointers to the node if it were expensive to copy.
This way you're never actually removing the element from T, simply moving on to look at the next item. Presumably it could be cleaned up at the end.
For the Dijkstra algorithm, you usually use a binary heap to implement a priority queue and visit nodes in ascending order of distance to source nodes. At each visit, neighboring distances may be updated (relax operation) so corresponding queue elements change priority (decrease-key operation).
Instead of using the distance directly as the key of heap elements, use the node identifier (or pointer). But also use a comparison function (as e.g. in std::make_heap and most STL algorithms) that, given two node identifiers, compares the corresponding distances.
This way, node identifiers are re-ordered according to heap operations and, whenever you pop an element from the heap (having minimal distance), you can access any information you like given its node identifier.
How do I efficiently copy an entire queue to a vector/an array in C++?
say I have a std::queue and at some point I want to copy it to a vector/an array and then sort it.
Thanks for everyone's answers.
What I really want to do is to create a window with a fix length and at some point i need to copy all the elements inside this window and sort them. the window is moving and there are new data coming in through another interface so i want to use queue. is there any better implementations?
You wrote:
What I really want to do is to create a window with a fix length and at some point i need to copy all the elements inside this window and sort them. the window is moving and there are new data coming in through another interface so i want to use queue.
I suggest to take a step back, and reconsider whether you really want to use a queue. I suppose you want it because you
want to expose a minimal interface to the other component which adds data to the queue.
efficient addition/removal of elements at the front/back (to implement the 'fixed width window' concept)
an efficient way to access the data visible in the window sorted
Unfortunately, std::queue isn't very suitable for (3). Hence, I'd suggest to look for something which addresses (2) and (3), and then consider writing a wrapper of some sort (maybe a plain function which just adds an element to the queue will do?) to implement (1).
For instance, I'd consider using a plain std::deque. It can add/remove elements from the beginning/end of the queue in constant time. It's also very easy to get a sorted view on the window, e.g. if copying the elements of the queue is cheap you could use std::sort like:
std::vector<Elem> sortedView( queue.begin(), queue.end() );
std::sort( sortedView.begin(), sortedView.end() );
...you could of course also do something more clever by not copying the data but rather creating a vector of iterators into the queue, or by using a different sorting algorithm like partial_sort.
If you just want to keep a sorted queue, take a look at priority_queue.
Honestly, the best option is to use the right STL data structure from the start. If you will want to sort the data, a std::queue is not the right data structure.
Consider using a map (or perhaps a hash map). Typical implementations of maps actually build the map sorted, with lookups being performed in O(ln) time. You can still iterate sequentially through a map too, if you really want to.
The only way to access std::queue elements is using a combination of front, back, push, pop since std::queue has no iterators. (In order to be able to use iterators, you should use the underlying container (e.g. std::deque) directly, instead of std::queue.
Since you want to make a copy (presumably leaving the elements in the queue as they were), you can push elements back into the queue after you pop them.
Also, since you know the size of the queue, you can use vector::reserve to prevent expensive memory reallocations triggered by vector::push_back.
So
std::vector<int> V;
std::queue<int> Q;
V.reserve(Q.size());
for(size_t numPos = 0; numPops < Q.size(); ++numPops) {
V.push_back(Q.front());
Q.pop();
Q.push(V.back());
}
std::sort(V.begin(), V.end());
I was wonndering about a queue-like container but which has key-access, like a map.
My goal is simple : I want a FIFO queue, but, if I insert an element and an element with a given key is already in the queue, I want it the new element to replaced the one already in the queue. For example, a map ordered by insertion time would work .
If there is no container like that, do you think it can be implemented by using both a queue and a map ?
Boost multi-index provides this kind of container.
To implement it myself, I'd probably go for a map whose values consist of a linked list node plus a payload. The list node could be hand-rolled, or could be Boost intrusive.
Note that the main point of the queue adaptor is to hide most of the interface of Sequence, but you want to mess with the details it hides. So I think you should aim to reproduce the interface of queue (slightly modified with your altered semantics for push) rather than actually use it.
Obviously what you want can be done simply with the queue-like container, but you would have to spend O(n) time on every insertion to determine if the element is already present. If you implement your queue based on something like std::vector you could use the binary search and basically speed up your insertion to O(log n) (that would still require O(n) operations when the memory reallocation is done).
If this is fine, just stick to it. The variant with additional container might give you a performance boost, but it's also likely to be error-prone to write and if the first solution is sufficient, just use it.
In the second scenario you might want to store your elements twice in different containers - the original queue and something like a map (or sometimes a hashmap may perform better). The map is used only to determine if the element is already present in the container or not - and if YES, you will have to update it in your queue.
Basically that gives us O(1) complexity for hashmap lookups (in real world this might get uglier because of the collisions - hashmaps aren't really good for determining element existence) and O(1) insertion time for the case when no update is required and O(n) insertion time for the case update is needed.
Based on the percentage of the actual update operations, the actual insertion performance may vary from O(1) to O(n), but this scheme will definitely outperform the first one if the number of updates is small enough.
Still, you have to insert your elements in two containers simultaneosly and the same should be done if the element is deleted and I would think twice "do I really need that performance boost?".
I see easy way of doing this with a queue and optionally a map.
Define some sort of == operator for your elements.
Then simply have a queue and search for your element every time you want to insert it.
You could optimize this by having a map of element locations to elements instead of searching the queue every time.