So, i'm coding one thing on c++, and i'm trying to implement a priority queue with pairing heaps. I want this priority to automatically increase over time, so that if the element (a class) has been in the heap for, say, 5 minutes, it's priority (a variable) is increased. And i have no clue how to make that happen.
I could implement a function which would check the duration for each element each set amount of time, but the problem is that it's pretty tough to check each and every element within a heap. So I think I need to do something withinin the elements, but I'm not sure what and how.
Is there any simple solution to that? I feel like i must be missing something, but if that's not the case, then I'd better drop this idea, because I have to finish this thing pretty soon.
UP: This program is meant for the human queue, so the reason for this idea is to not make people wait for too long. The priority is arbitrary, there are priority "levels" set for each element when it's added, so making the time the priority is not a solution for me.
You can add the elements to a linked list:
A new element is added to the end of the list
When the first element is in heap for 5 mins, its priority increased and it is moved to the end of the list.
This way you can check only the first element. Another advantage is that you can set the timer to the value the first element is to be checked in. That is, no need to do unnecessary periodical checks.
Related
Consider I have a min priority queue with the smallest value on the top, I hope to reduce the value on the top so that the property of the queue would still be maintained and time complexity would be O(1). How to do that?
I have seen the question here how to change the value of std::priority_queue top()?
Where take the value out, modify it and push it back basically would be O(logN) complexity, I wonder can I make use of the property of reducing the value so that there is no need to push the value back again?
The standard priority queue doesn't support changing the keys.
What you are looking for is something similar to another data structure called Indexed Priority Queue, often used by Dijkstra algorithm.
The Indexed Prioirty queue supports 2 more methods in it's API: increaseKey and decreaseKey enabling modifying the key's itself.
The STL doesnt define indexed priority queue. You'd probably need to implement one by yourself or look for some third party implementation.
I see the point of this question differently from others. Based on this question,
I have a min priority queue with the smallest value on the top, I hope to reduce the value on the top so that the property of the queue would still be maintained and time complexity would be O(1).
With std::priority_queue, you can't. We may try a hack like const_cast<int &>(pq.top()) = lesser_value_than_top. It could work in some implementations, but it is NOT safe.
So, I would like to suggest building your own PQ with an array-based heap, and you can just change the top's value without log(N) work, as long as it is a value equal or less than the current top.
this is a question regarding writing your own data structure programs (which appears to be called implementation I think?). I am using C++ to write.
When I did a stack assignment, popping something off the stack simply changed the index of the top variable as it was more about where the user can access items vs actually physically removing the item (it's not accessible once the top variable is changed, so my professor said these things don't actually need to be deleted/removed). Once top is moved down, there's more room for items on top.
In a queue, my understanding is that one dequeues from the front (first in, first out). When this happens, would all the remaining items need to be moved up one index?
For example, if I have a queue of 3, 5, 7 and I dequeue one, would I simply have an int variable called "front" that I increment from 0 to 1 so that front is now at the index for number 5? My concern is that by doing this, the queue will no longer be able to hold the max number of items, so I would think that I would move everyone down one index so that there is still room to add things at the back.
TLDR yes, I would say you should move the elements
Let's start from the beginning:
When I did a stack assignment, [...] my professor said these things
don't actually need to be deleted/removed
It's important (imho) to understand why the professor said this.
First you need to be aware that this strategy works only for element types that have a trivial destructor (e.g. basic data types like int). This is a restriction of your particular implementation of the stack. Another limitation of your stack is that is has a limiting max capacity. A proper queue structure like std::stack has none of these shortcomings. This is perfectly fine for your assignment because implementing a stack without those restrictions would involve dynamic memory allocations and/or advanced techniques like placement new (or use an underlying container that already does all of this like std::deque). But the point of the assignment is to teach you the concepts of stack. Learning one new thing can be difficult. Learning 3 new and unrelated complex things at the same time would be irresponsible. So that's why your professor said "these things don't actually need to be deleted/removed".
Now let's go to the queue structure. Regardless of your choice your queue still has the above two limitations: applicable only for types with trivial destructor and unable to deal with unlimited elements.
If you move the elements then your queue will have the limitation of a (relatively small) maximum capacity (just like the stack you implemented)
If you don't move the elements then your queue will be limited to a maximum number of push operations, regardless of the pop operations. Just like you identified. So when the maximum push operations have been reached you can't push into the queue anymore, even if you poped or pop elements out of it.
The latter one is obviously more limited then the former. But since you already are supposed to implement a queue with limited capabilities the question is if the more limited one and the most easy to implement is acceptable in your exercise or not. Only your professor can clarify this. He/she can say something along the lines: "I am only interested you learn the abstract concepts of the queue and such you can assume/imagine an infinite capacity; you just need to deal with the indices and the correctness of push/pop operations". Or he/she can except you move the elements since it might be something you are already supposed to know how to do. However I would recommend to implement the moves regardless because it is not that difficult and is an useful skill.
As noted in the comments there are other ways of implementing a queue, like a circular queue.
I have a queue with n elements in it and the front is at 0. I need to create a stack of these numbers with 0 at the top.
It can only be done with EnQueue, DeQueue, Push, and Pop, and constant storage. I dont need an answer so much as an idea of how I could approach this problem.
Please don't answer this for me, but just try to understand I'm new at programming and could just use an idea of what is a way this can be done.
Is it a Towers-of-Hanoi-like approach?
Does that only use a constant storage?
This isnt for homework, I just need some advice on how to proceed. My first idea, reversing the queue and then pushing it did not work. I even tried sketching out other situations with no avail. Then I wondered if dequeueing and pushing them all, then popping and enqueueing them all, then dequeue and push again.
Is this efficient?
Does this use constant storage?
I am still learning fundamental programming concepts. Please be nice! :)
What am I facing?
The biggest problem you are facing is that your two containers aren't directly compatible with each other.
A queue is normally a FIFO1 container, while a stack is LIFO2. This means that you cannot just copy the data in sequential order from your queue to your stack, since that will make the elements appear in the "wrong" order (following your description).
Another problem is that there is no good way (performance wise) to reverse a queue. A queue is a one-way container, internally an element only has to know about the next element in line, not about the previous one. This means that you cannot iterate through the queue starting at the back, and that iteration always is O(n).
The same problem is with your stack.
The things described earlier put together makes this quite a tedious problem, though there are solutions they aren't always the most straight forward.
Hints on how to solve this issue..
You'll need some sort of intermediate state to store your elements, or could we use the LIFO/FIFO properties of our containers to our advantage?
Below is an implementation which does what you want, if you don't want to know the answer to your question don't hover with your mouse over this gray area.
It will require some additional storage since space for an extra element will be allocated during copying from one container to another.. this is inevitable, though the storage is constant.
Remember that the copy-initialization can be optimized by using rvalue-references and move in C++11.
Can't seem to get syntax highlighting working inside a spoiler..
Sample implementation can be found here.
It takes advantage of the fact that a queue is FIFO and stack LIFO, by copying the data queue to stack, then stack to queue and finally queue to stack again we have effectively reversed the order of elements in a way that will match your description.
footnotes
1. FIFO = First In First Out
2. LIFO = Last In First Out
DeQueue everything from Queue, immediately Pushing each element to Stack. Now Pop everything from Stack, immediately EnQueueing to Queue. What's in Queue now?
Presuming your Queue and Stack hold fixed sized items, the above ahem subroutine certainly only uses constant additional storage: Only storage for 1 item is needed as each item transits from Queue to Stack or vice-versa.
Edit: As you point out, my subroutine reverses the content of the Queue. Having done so, it is fairly simple to drain the Queue into the Stack again to get the desired outcome.
And, as you point out, this requires transferring 3n = O(n) items, where n is the initial size of the Queue. Could you do better? I don't believe so, or at least not significantly. In some sense, without even a counter (which would take O(log n) > O(1) extra storage), the only reasonable thing to do is drain the queue into the stack or vice versa.
I do not have formal CS training, so bear with me.
I need to do a simulation, which can abstracted away to the following (omitting the details):
We have a list of real numbers representing the times of events. In
each step, we
remove the first event, and
as a result of "processing" it, a few other events may get inserted into the list at a strictly later time
and repeat this many times.
Questions
What data structure / algorithm can I use to implement this as efficiently as possible? I need to increase the number of events/numbers in the list significantly. The priority is to make this as fast as possible for a long list.
Since I'm doing this in C++, what data structures are already available in the STL or boost that will make it simple to implement this?
More details:
The number of events in the list is variable, but it's guaranteed to be between n and 2*n where n is some simulation parameter. While the event times are increasing, the time-difference of the latest and earliest events is also guaranteed to be less than a constant T. Finally, I suspect that the density of events in time, while not constant, also has an upper and lower bound (i.e. all the events will never be strongly clustered around a single point in time)
Efforts so far:
As the title of the question says, I was thinking of using a sorted list of numbers. If I use a linked list for constant time insertion, then I have trouble finding the position where to insert new events in a fast (sublinear) way.
Right now I am using an approximation where I divide time into buckets, and keep track of how many event are there in each bucket. Then process the buckets one-by-one as time "passes", always adding a new bucket at the end when removing one from the front, thus keeping the number of buckets constant. This is fast, but only an approximation.
A min-heap might suit your needs. There's an explanation here and I think STL provides the priority_queue for you.
Insertion time is O(log N), removal is O(log N)
It sounds like you need/want a priority queue. If memory serves, the priority queue adapter in the standard library is written to retrieve the largest items instead of the smallest, so you'll have to specify that it use std::greater for comparison.
Other than that, it provides just about exactly what you've asked for: the ability to quickly access/remove the smallest/largest item, and the ability to insert new items quickly. While it doesn't maintain all the items in order, it does maintain enough order that it can still find/remove the one smallest (or largest) item quickly.
I would start with a basic priority queue, and see if that's fast enough.
If not, then you can look at writing something custom.
http://en.wikipedia.org/wiki/Priority_queue
A binary tree is always sorted and has faster access times than a linear list. Search, insert and delete times are O(log(n)).
But it depends whether the items have to be sorted all the time, or only after the process is finished. In the latter case a hash table is probably faster. At the end of the process you then would copy the items to an array or a list and sort it.
I have about 18 million elements in an array that are initialized and ready to be used by a simple manager called ElementManager (this number will later climb to a little more than a billion in later iterations of the program). A class, A, which must use the elements communicates with ElementManager that returns the next available element for consumption. That element is now in use and cannot be reused until recycled, which may happen often. Class A is concurrent, that is, it can ask ElementManager for an available element in several threads. The elements in this case is an object that stores three vertices to make a triangle.
Currently, the ElementManager is using Intel TBB concurrent_bounded_queue called mAllAvailableElements. There is also another container (a TBB concurrent_vector) that contains all elements, regardless of whether they are available for use or not, called mAllElements. Class A asks for the next available element, the manager tries to pop the next available element from the queue. The popped element is now in use.
Now when class A has done what it has to do, control is handed to class B which now has to iterate through all elements that are in use and create meshes (to take advantage of concurrency, the array is split into several smaller arrays to create submeshes which scales with the number of available threads - the reason for this is that creating a mesh must be done serially). For this I am currently iterating over the container mAllElements (this is also concurrent) and grabbing any element that is in use. The elements, as mentioned above, contain polygonal information to create meshes. Iteration in this case takes a long time as it has to check each element and query whether it is in use or not, because if it is not in use then it should not be part of a mesh.
Now imagine if only 1 million out of the possible 18 million elements were in use (but more than 5-6 million were recycled). Worse yet, due to constant updates to only part of the mesh (which happens concurrently) means the in use elements are fragmented throughout the mAllElements container.
I thought about this for quite some time now and one flawed solution that I came up with was to create another queue of elements named mElementsInUse, which is also a concurrent_queue. I can push any element that is now in use. Problem with this approach is that since it is a queue, any element in that queue can be recycled at any time (an update in a part of the mesh) and declared not in use and since I can only pop the front element, this approach fails. The only other approach I can think of is to defragment the concurrent_vector mAllElements every once in a while when no operations are taking place.
I think my approach to this problem is wrong and thus my post here. I hope I explained the problem in enough detail. It seems like a common memory management problem, but I cannot come up with any search terms to search for it.
How about using a bit vector to indicate which of your elements are in use? It's easy to partition it for parallel processing when building your full mesh, and you can use atomic operations on words in the vector and thus avoid locks.