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]);
Related
I am currently studying about Algorithms & Data Structures and while I was reading over the Book of Algorithms 4th edition, I discovered the Bag data-structure together with the Stack and Queue.
After reading the the explanation of it, it is still unclear to me why would I prefer using a Bag (which has no remove() method) over other data-structures such as Stack, Queue, LinkedList or a Set?
As far as I can understand from the Book, the implementation of a Bag, is the same as for a Stack, just replacing the name of push() to add() and remove the pop() method.
So the idea of a Bag is basically having the ability to collect items and then iterate through the collected items, check if a bag is empty and find the number of items in it.
But under which circumstances I would better using a Bag over one of the mentioned above Collections? And why a Bag doesn't have a remove() method basically? is there a specific reason for it?
Thanks in advance.
Stack is ADT of the collection of elements with specific remove order = LIFO (last-in-first-out), allows duplicates,
Queue is ADT of the collection of elements with specific remove order = FIFO (first-in-first-out), allows duplicates,
LinkedList is implementation of the list,
Set is ADT of the collection of elements which disallows duplicates,
Bag is ADT of the collection of elements which allows duplicates.
In general, anything that holds an elements is Collection.
Any collection which allows duplicates is Bag, otherwise it is Set.
Any bag which access elements via index is List.
Bag which appends new element after the last one and has a method to remove element from the head (first index) is Queue.
Bag which appends new element after the last one and has a method to remove element from the tail (last index) is Stack.
Example: In Java, LinkedList is a collection, bag, list, queue and also you can work with it as it was a stack since it support stack operations (add~addLast~push, peekLast, removeLast~pop), so you can call it also stack. The reason, why it does not implement Stack interface is, that peek method is reserved by Queue implementation which retrieves the head of the list (first element). Therefore in case of LinkedList, the "stack methods" are derived from Deque.
Whether Bag contains remove(Object) or not may depend on the implementation e. g. you can implement your own Bag type which supports this operation. Also you can implement get(int) operation to access object on specified index. Time complexity of the get(int) would depend on your implementation e. g. one can implement Bag via linked-list so the complexity would be at average O(n/2), other one via resizable array (array-list) with direct access to the element via index, so the complexity would be O(1).
But the main idea of the Bag is, that it allows duplicates and iteration through this collection. Whether it supports another useful operations depends on implementator's design decision.
Which one of the collection type to use dependes on your needs, if duplicates are not desired, you would use Set instead of Bag. Moreover, if you care about remove order you would pick Stack or Queue which are basically Bags with specific remove order. You can think of Bag as super-type of the Stack and Queue which extends its api by specific operations.
Most of the time, you just need to collect objects and process them in some way (iteration + element processing). So you will use the most simple Bag implementation which is one directional linked-list.
Bag is an unordered collection of values that may have duplicates. When comparing a stack to a bag, the first difference is that for stacks,
order matters.
Bag only supports the add and iterate operations. You cannot remove items from a bag-it’s possible to remove elements from a stack.-. After checking if the container is actually empty, clients can iterate through its elements; since the actual order is unspecified by definition, clients must not rely on it.
Bags are useful when you need to collect objects and process them as a whole set rather than individually. For example, you could collect samples and then, later, compute statistics on them, such as average or standard deviation—the order is
irrelevant in that case.
in terms of priority queues, a bag is a Priority queue for which element
removal (top()-Returns and extracts the element with the highest priority. ) is disabled. Priority Queue api has, top, peek,insert,remove and update methods. it’s possible to peek one element at a time, and the
priority of each element is given by a random number from a uniform distribution. Priorities also change at every iteration.
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.
If I need to remove elements in a list, will the following be better than using LinkedList:
int j = 0;
List list = new ArrayList(1000000);
...
// fill in the list code here
...
for (Iterator i = list.listIterator(); i.hasNext(); j++) {
if (checkCondition) {
i.remove();
i = list.listIterator(j);
}
}
?
LinkedList does "remove and add elements" more effectively than ArrayList, but LinkedList as a doubly-linked list needs more memory, since each element is wrapped as an Entry object. While I need a one-direction List interface, because I'm running over in ascending order of index.
The answer is: it depends on the frequency and distribution of your add and removes. If you have to do only a single remove infrequently, then you might use a linked list. However, the main killer for an ArrayList over a LinkedList is constant time random access. You can't really do this with a normal linked list (however, look at a skip list for some inspiration..). Instead, if you're removing elements relative to other elements (where, you need to remove the next element) then you should use a linked list.
There is no simple answer to this:
It depends on what you are optimizing for. Do you care more about the time taken to perform the operations, or the space used by the lists?
It depends on how long the lists are.
It depends on the proportion of elements that you are removing from the lists.
It depends on the other things that you do to the list.
The chances are that one or more of these determining factors is not predictable up-front; i.e. you don't really know. So my advice would be to put this off for now; i.e. just pick one or the other based on gut feeling (or a coin toss). You can revisit the decision later, if you have a quantifiable performance problem in this area ... as demonstrated by cpu or memory usage profiling.
I am trying to to understand why Java's ArrayDeque is better than Java's LinkedList as they both implement Deque interface.
I hardly see someone using ArrayDeque in their code. If someone sheds more light into how ArrayDeque is implemented, it would be helpful.
If I understand it, I will be more confident using it. I could not clearly understand the JDK implementation as to the way it manages head and tail references.
Linked structures are possibly the worst structure to iterate with a cache miss on each element. On top of it they consume way more memory.
If you need add/remove of the both ends, ArrayDeque is significantly better than a linked list. Random access each element is also O(1) for a cyclic queue.
The only better operation of a linked list is removing the current element during iteration.
I believe that the main performance bottleneck in LinkedList is the fact that whenever you push to any end of the deque, behind the scene the implementation allocates a new linked list node, which essentially involves JVM/OS, and that's expensive. Also, whenever you pop from any end, the internal nodes of LinkedList become eligible for garbage collection and that's more work behind the scene.
Also, since the linked list nodes are allocated here and there, usage of CPU cache won't provide much benefit.
If it might be of interest, I have a proof that adding (appending) an element to ArrayList or ArrayDeque runs in amortized constant time; refer to this.
All the people criticizing a LinkedList, think about every other guy that has been using List in Java probably uses ArrayList and an LinkedList most of the times because they have been before Java 6 and because those are the ones being taught as a start in most books.
But, that doesn't mean, I would blindly take LinkedList's or ArrayDeque's side. If you want to know, take a look at the below benchmark done by Brian (archived).
The test setup considers:
Each test object is a 500 character String. Each String is a different object in memory.
The size of the test array will be varied during the tests.
For each array size/Queue-implementation combination, 100 tests are run and average time-per-test is calculated.
Each tests consists of filling each queue with all objects, then removing them all.
Measure time in terms of milliseconds.
Test Result:
Below 10,000 elements, both LinkedList and ArrayDeque tests averaged at a sub 1 ms level.
As the sets of data get larger, the differences between the ArrayDeque and LinkedList average test time gets larger.
At the test size of 9,900,000 elements, the LinkedList approach took ~165% longer than the ArrayDeque approach.
Graph:
Takeaway:
If your requirement is storing 100 or 200 elements, it wouldn't make
much of a difference using either of the Queues.
However, if you are developing on mobile, you may want to use an
ArrayList or ArrayDeque with a good guess of maximum capacity
that the list may be required to be because of strict memory constraint.
A lot of code exists, written using a LinkedList so tread carefully when deciding to use a ArrayDeque especially because it DOESN'T implement the List interface(I think that's reason big enough). It may be that your codebase talks to the List interface extensively, most probably and you decide to jump in with an ArrayDeque. Using it for internal implementations might be a good idea...
ArrayDeque is new with Java 6, which is why a lot of code (especially projects that try to be compatible with earlier Java versions) don't use it.
It's "better" in some cases because you're not allocating a node for each item to insert; instead all elements are stored in a giant array, which is resized if it gets full.
ArrayDeque and LinkedList are implementing Deque interface but implementation is different.
Key differences:
The ArrayDeque class is the resizable array implementation of the Deque interface and LinkedList class is the list implementation
NULL elements can be added to LinkedList but not in ArrayDeque
ArrayDeque is more efficient than the LinkedList for add and remove operation at both ends and LinkedList implementation is efficient for removing the current element during the iteration
The LinkedList implementation consumes more memory than the ArrayDeque
So if you don't have to support NULL elements && looking for less memory && efficiency of add/remove elements at both ends, ArrayDeque is the best
Refer to documentation for more details.
I don't think ArrayDeque is better than LinkedList. They are different.
ArrayDeque is faster than LinkedList on average. But for adding an element, ArrayDeque takes amortized constant time, and LinkedList takes constant time.
For time-sensitive applications that require all operations to take constant time, only LinkedList should be used.
ArrayDeque's implementation uses arrays and requires resizing, and occasionally, when the array is full and needs to add an element, it will take linear time to resize, resulting the add() method taking linear time. That could be a disaster if the application is very time-sensitive.
A more detailed explanation of Java's implementation of the two data structures is available in the "Algorithms, Part I" course on Coursera offered by Princeton University, taught by Wayne and Sedgewick. The course is free to the public.
The details are explained in the video "Resizing Arrays" in the "Stacks and Queues" section of "Week 2".
although ArrayDeque<E> and LinkedList<E> have both implemented Deque<E> Interface, but the ArrayDeque uses basically Object array E[] for keeping the elements inside its Object, so it generally uses index for locating the head and tail elements.
In a word, it just works like Deque (with all Deque's method), however uses array's data structure. As regards which one is better, depends on how and where you use them.
That's not always the case.
For example, in the case below linkedlist has better performance than ArrayDeque according to leetcode 103.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> rs=new ArrayList<>();
if(root==null)
return rs;
// 👇 here ,linkedlist works better
Queue<TreeNode> queue=new LinkedList<>();
queue.add(root);
boolean left2right=true;
while(!queue.isEmpty())
{
int size=queue.size();
LinkedList<Integer> t=new LinkedList<>();
while(size-->0)
{
TreeNode tree=queue.remove();
if(left2right)
t.add(tree.val);
else
t.addFirst(tree.val);
if(tree.left!=null)
{
queue.add(tree.left);
}
if(tree.right!=null)
{
queue.add(tree.right);
}
}
rs.add(t);
left2right=!left2right;
}
return rs;
}
}
Time complexity for ArrayDeque for accessing a element is O(1) and that for LinkList is is O(N) to access last element. ArrayDeque is not thread safe so manually synchronization is necessary so that you can access it through multiple threads and so they they are faster.
This were the questions I was asked in the interview fews days back and I was not sure about the approach. Suggestions would be highly appreciated:
How can I have implement PriorityQueue interface to get queue() method in O(1) and dequeue() method in O(n).
How can I have implement PriorityQueue interface to get queue() method in O(n) and dequeue() method in O(1).
Thanks.
A typical PriorityQueue implementation would use a Heap to get O(lg n) performance for the "add" operation, so O(n) performance will be even easier.
For example, you could use a vector or linked list as the underlying data structure. For O(1) "add" you can simply add the new value to the end and for O(n) "remove" you can do a linear search for the min value. Conversely, for O(n) "add" you can do a linear scan to find the next largest value then insert before it, for O(1) remove you can simply remove the first element of the list.
queue() method in O(1) and dequeue() method in O(n):
Use a linked list and simply add every new entry directly to the head of the list in queue(). In dequeue() iterate the list and remove and return the entry with the highest priority.
queue() method in O(n) and dequeue() method in O(1):
Use a linked list again. But this time in queue() you iterate over the entries to put the new entry into it's priority sorted position (this is actually one step of an insertion sort). In dequeue() you can now always remove and return the first element of the list.
Just take a look at:
http://www.docjar.com/html/api/java/util/PriorityQueue.java.html
Remember, all good programmers copy good code :P
I assume you have the basic understanding about data structures, list, maps, etc. If you dont, understanding how this work will not make much sense, instead go and investigate about the subject further.
I would have said that PriorityQueue isn't an interface, it's a class, and I wouldn't implement anything that was O(n) if I could help it.
For an O(1) approach to the queue() method you must keep track of the last element of your queue, so that you can easily append one more after it, regardless the size of your queue.
For an O(n) in queue() and O(1) in dequeue() you need to keep track of the first element of your queue in a variable, so that regardless the number of elements within it, you can remove the first from the list with always a single set of instructions (no iterations).
In each of both cases you just add one extra variable to your class.
Wikipedia has a solution for this--
http://en.wikipedia.org/wiki/Priority_queue#Naive_implementations
For O(1) insertion, add element to the current location and for dequeue in O(n) perform a search based on priority..
For O(n) insertion perform the search initially based on priority and add the element and for dequeue in O(1) just remove the element from the beginning or from 0th location...
The code in this example can help you understand more clearly.
http://www.java-forums.org/java-lang/7449-how-implement-priority-queue-java.html
In the above example, the dequeue takes O(1) and insertion takes O(n)