I define a maximum priority queue as below:
PriorityQueue<Integer> queue = new PriorityQueue<>(Collections.reverseOrder());
queue.add(25);
queue.add(3);
queue.add(1);
queue.add(3);
queue.add(4);
I need to understand how this works especially when does the 1 gets the index of 2 only (not 4)?
Thanks.
It has no guaranteed order (https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/PriorityQueue.html):
The Iterator provided in method iterator() and the Spliterator provided in method spliterator() are not guaranteed to traverse the elements of the priority queue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()).
Normally you retrieve elements according to their natural order using the poll() method, for example:
while (!queue.isEmpty()) {
var element = queue.poll();
...
}
EDIT:
If you want to look at the internals of the class, this part of the code may be relevant (it basically uses a heap data structure):
/**
* Priority queue represented as a balanced binary heap: the two
* children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The
* priority queue is ordered by comparator, or by the elements'
* natural ordering, if comparator is null: For each node n in the
* heap and each descendant d of n, n <= d. The element with the
* lowest value is in queue[0], assuming the queue is nonempty.
*/
transient Object[] queue;
This class use structure called Heap, and store it in array.
You will receive objects in proper order when you poll them.
Related
I have a question regarding implementing priority queue for Dijkstra's algorithm, because this is a hw so I couldn't create another class, so I'm trying to find a way to add nodes(integer)in priority queue but I want the queue to sort the weight inside the node, but not the node itself.
For example,I have 3 nodes(0,1,2) and node 0 has a weight of 10, node 1 has 15, and node 2 has 5.
Queue<Integer> queue = new PriorityQueue<Integer>();
queue.add(0);
queue.add(1);
queue.add(2);
while(!queue.isEmpty()){
System.out.println(queue.poll());
}
This should give me a output of 2,0,1.
Is this possible without creating another class? Or is there a different approach I could use besides priority queue?
Thanks in advance!!!!!! any help would be much appreciated!
One solution I could think of is sorting a normal queue every time I add a node into it, so if I have node 2,0,1 in the queue and I want to add node 3 which has a weight of 8, I would need to compare the weight with the top element of queue until it fits into the queue, so it would be 2,3,0,1 in queue, but this is kindda inefficient tho.
You have two options:
Create your own Node class, and make it implement the Comparable<Node> interface. The class will have a weight attribute, and it could compare Nodes based on their weight. This will create a natural ordering of Nodes that PriorityQueue will use.
Create the priority queue with the PriorityQueue(Comparator<? super E> comparator) constructor. It takes a comparison function (Comparator) for comparing two items. You can therefore have that function compare using the node's weights (which don't have to be kept in the same queue - the might be calculated dynamically or be kept in some separate data structure).
This is straight from the Java Docs:
This class and its iterator implement all of the optional methods of the Collection and Iterator interfaces. The Iterator provided in method iterator() is not guaranteed to traverse the elements of the priority queue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()).
So basically, my PriorityQueue works fine, but printing it out to the screen using its own built in toString() method caused me to see this anomaly in action, and was wondering if someone could explain why it is that the iterator provided (and used internally) does not traverse the PriorityQueue in its natural order?
Because the underlying data structure doesn't support it. A binary heap is only partially ordered, with the smallest element at the root. When you remove that, the heap is reordered so that the next smallest element is at the root. There is no efficient ordered traversal algorithm so none is provided in Java.
PriorityQueues are implemented using binary heap.
A heap is not a sorted structure and it is partially ordered. Each element has a “priority” associated with it. Using a heap to implement a priority queue, it will always have the element of highest priority in the root node of the heap. so in a priority queue, an element with high priority is served before an element with low priority. If two elements have the same priority, they are served according to their order in the queue. Heap is updated after each removal of elements to maintain the heap property
At first guess, it's probably traversing the data in the order in which it's stored. To minimize the time to insert an item in the queue, it doesn't normally store all the items in sorted order.
Well, as the Javadoc says, that's how it's been implemented. The priority queue probably uses a binary heap as the underlying data structure. When you remove items, the heap is reordered to preserve the heap property.
Secondly, it's unwise to tie in a specific implementation (forcing a sorted order). With the current implementation, you are free to traverse it in any order and use any implementation.
Binary heaps are an efficient way of implementing priority queues. The only guarantee about order that a heap makes is that the item at the top has the highest priority (maybe it is the "biggest" or "smallest" according to some order).
A heap is a binary tree that has the properties:
Shape property: the tree fills up from top to bottom left to right
Order prperty: the element at any node is bigger (or smaller if smallest has highest priority) than its two children nodes.
When the iterator visits all the elements it probably does so in a level-order traversal, i.e. it visits each node in each level in turn before going on to the next level. Since the only guarantee about order that is made that a node has a higher priority than its children, the nodes in each level will be in no particular order.
I'm just studying for exams right now, and came across this question in the sample exam:
Block Implementation of a Priority Queue
If we know in advance that a priority queue will only ever need to cater for a small number of discrete priorities (say 10), we can implement all operations of the priority queue in constant time by representing the priority queue as an array of queues - each queue storing the elements of a single priority. Note that while an operation may be linear in the number of priorities in the priority queue, the operation is still constant with respect to the size of the overall data structure.
The Objects stored in this priority queue is not comparable.
I have attempted it but I am lost as to how I am supposed to assign priority with a array implementation priority queue.
I have also tried looking for solutions, but all I've managed to find are examples that used Comparable, which we did not learn in this course.
Question: http://imgur.com/3mlBoW7
Each of the arrays will correspond to a different priority. Your lowest level priority array will deal only with objects of that priority level. Your highest level priority array will deal with objects of highest priority level, and so on. When you receive a new object, you place it into the array that corresponds to its priority.
It doesn't matter, then, that objects are not comparable since they are sorted by priority based on the stratification of the arrays. Then, when you are looking for next elements to execute, you check the highest priority array and see if there are any elements; if not, move to the next priority, and so on through each array.
I'm hoping I understood the problem and your question correctly; let me know if you have any additional questions in regards to my answer.
Following on Imcphers' answer, this would be a simple implementation in Java. Note that you do not need Comparable because enqueue takes an extra parameter, namely the discrete priority of the newly-added element:
public class PQueue<T> {
public static final int MAX_PRIORITIES = 10;
private ArrayList<ArrayDeque<T> > queues = new ArrayList<>();
public PQueue() {
for (int i=0; i<MAX_PRIORITIES; i++) {
queues.add(new ArrayDeque<T>());
}
}
public void enqueue(int priority, T element) {
// ... add element to the end of queues[priority]
}
public T dequeue() {
// ... find first non-empty queue and pop&return its first element
}
// ... other methods
}
Here, enqueue() and dequeue() are both O(1), because you know in advance how many priorities there can be, and what their values are (0 to MAX_PRIORITIES-1) so that no sorting is required, and search of a non-empty queue is constant-time (at most, MAX_PRIORITIES queues will have to be tested for emptyness). If these parameters are not known, the best implementation would use
private TreeSet<ArrayDeque<T extends Comparable> > queues
= new TreeSet<>(CustomComparator);
Where the CustomComparator asks queues to sort themselves depending on the natural order of their first elements, and which needs to keep these internal queues sorted after each call to enqueue --- this ups the complexity of enqueue/dequeue to O(log p), where p is the number of distinct priorities (and therefore, internal queues).
Note that Java's PriorityQueue belongs to the same complexity class, but avoids all that object overhead contributed by the TreeSet / ArrayDeque wrappers by implementing its own internal priorty heap.
So I am playing with the source code of the java.util.PriorityQueue. You can check it here: http://kickjava.com/src/java/util/PriorityQueue.java.htm
I am in need to peek the tail of the queue. This class only offers peeking the head of the queue. Is there an easy way that I can modify this class to allow me to pick the tail?
I am looking for any change / smart hack in this class to allow me to do that. My first try was to peek queue[size] but it did not work.
Java's PriorityQueue, like most priority queues, is implemented with a heap.
A heap is a data structure that maintains only the property that all parents are less than their children, or all parents are greater than their children. There is no inherent ordering among children.
Thus, the only way to find the tail would be to do a linear search among the bottom layer, which costs O(n) time for a size n priority queue.
Yes, but the at the cost of extra space complexity:
PriorityQueue<Integer> pqNew = new PriorityQueue<>(java.util.Collections.reverseOrder());
Now add the elements of your PriorityQueue into this pqNew.
Therefore, pqNew.peek() will give you the required answer i.e. the tail element of your original PriorityQueue.
How about use toArray() method and access the last position?
PriorityQueue<Integer> pq = new PriorityQueue<>(3);
pq.offer(1); pq.offer(2); pq.offer(3);
System.out.println((int) pq.toArray()[pq.size()-1]);
I know, queue follow FIFO(First in first out) order, but I am not sure why the following output appears with below java sample program
JAVA Sample
public static void main(String args[]) {
Queue<String> q = new PriorityQueue<String>();
q.add("3");
q.add("1");
q.add("2");
Iterator<String> itr = q.iterator();
while (itr.hasNext()) {
System.out.println(itr.next() + " ");
}
}
OUTPUT :
1
3
2
As per Java doc of java.util.PriorityQueue.PriorityQueue()
Creates a PriorityQueue with the default initial capacity (11) that orders its elements according to their natural ordering.
Q1) Could any body please explain why the output is 1 3 2 and how
the natural order works here.
Q2) I have checked about natural ordering and its related to the
Comparable/Comparor but doesn't they are for
Sorting(Ascending/Descending) Order only??
The PriorityQueue in Java is a datastructure, that sorts the elements it contains. Excerpt from the Javadoc:
The elements of the priority queue are ordered according to their natural ordering, or by a Comparator provided at queue construction time, depending on which constructor is used.
The Problem with the unordered output comes from the iterator implementation. Another excerpt, this time from the iterator() method:
Returns an iterator over the elements in this queue. The iterator does not return the elements in any particular order.
So you don't java a fixed order with the iterator. If you use the poll() method in a loop you would get all given elements in ascending order.
If you are looking for a Queue in the FIFO-sense you may have a look at the LinkedList and only use the addFirst() and getLast() methods.