I want to know why we always use Sorting algorithm like (Insertion Sort or Merge Sort,...) just for lists and arrays? And why we do not use these algorithms for stack or queue?
Stacks and queues are abstract data types that have their own sense of order, i.e. LIFO (Last In First Out) for stacks and FIFO (First In First Out) for queues. As such, it does not make sense to take a queue/stack and reorder their elements around.
Wikipedia references
Stack (data structure)
Queue (data structure)
On Stack vs Vector
You may notice that in Java, java.util.Stackextendsjava.util.Vector, and since it makes sense to sort a Vector, perhaps it also makes sense to sort a Stack. This is not the case however; the fact that Stack extends Vector is in fact a design blunder. A stack is NOT a vector.
Related questions
Java Stack class inherit Vector Class
On using Collections.sort on java.util.Stack
Despite the fact that it doesn't make sense to use, say, quicksort on a stack, you CAN actually use Collections.sort on a java.util.Stack. Why? Because, by virtue of design error (this can't be emphasized enough!), a java.util.Stack is a java.util.Vector, which implements java.util.List, and you certainly can sort a List. Here's an example:
Stack<Integer> stack = new Stack<Integer>();
stack.push(1);
stack.push(3);
stack.push(5);
stack.push(2);
stack.push(4);
Collections.sort(stack); // by virtue of design error!!!
System.out.println(stack); // prints "[1, 2, 3, 4, 5]"
while (!stack.isEmpty()) {
System.out.println(stack.pop());
} // prints "5", "4", "3", "2", "1"
Note that the elements are printed in descending order: this is because of how java.util.Stack is implemented. It pushes to and pops from the end of the Vector. You don't need to know this; you shouldn't have known this; but these are the facts.
On using an appropriate data structure
Depending on what it is that you're trying to accomplish, a TreeSet may be the appropriate data structure. It is a Set, so it does not permit duplicate elements.
NavigableSet<Integer> nums = new TreeSet<Integer>();
nums.add(5);
nums.add(3);
nums.add(1);
nums.add(2);
nums.add(6);
System.out.println(nums.pollFirst()); // prints "1"
System.out.println(nums.pollFirst()); // prints "2"
nums.add(4);
System.out.println(nums.pollFirst()); // prints "3"
System.out.println(nums.pollFirst()); // prints "4"
That's because the order of a stack or a queue is part of the definition of these data structures. If we sorted them, they wouldn't be stacks or queues.
As others noted, in general it doesn't make sense to order stacks and queues. Just to make the picture full, there is an exception: PriorityQueue, which keeps its elements ordered.
A Stack or Queue are concepts which differ from Sequences. Arrays and Linked Lists represent Sequences, on which you can think of them as sorted or unsorted.
Stack and Queue have their own unique structure.
Stack is a structure that applies Last In First Out(LIFO). If you ordered a Stack, then it would violate LIFO.
Think that I add 7, 3, 5, 4 to a stack.
As you know, stack can only retrieve the last added element. Whenever, we call pop() method, it will retrieve 4.
However, think that you now sort it. It becomes 3, 4, 5, 7 and when we pop(), it will retrieve 7 which was the first element that we added. This violates LIFO rule.
The same is valid for Queue, because Queue structure applies First in First Out. If you have any question, please don't hesitate to ask.
First of all Stack and Queues are also list but having some special characteristics. Since they are list you can always sort them but if you do that you might alter properties of these data structures.
Then there will be no point to using these data structure throughout your code and at some point sort them to loose their property for which we were using them.
Related
Of my knowledge, there are the following implementations:
ArrayList
LinkedList
Vector
Stack
(based on http://tutorials.jenkov.com/java-collections/list.html pls correct if wrong)
ArrayList is a dynamic array implementation, so, as array, get is O(1), LinkedList has O(1) for get from Head, Vector and Stack are based on ArrayList, hence, O(1).
So in EVERY case get(0) on any built-in (cause you can make your own, for a specific purpose on making get(0) TS of O(n!)) implementation of List if O(1)?
Is get(0) on java.util.List always O(1)?
Let us assume that there is a parameter N which stands for the length of the list1.
For the 4 implementations of List that you mentioned, get(0) is indeed an O(1) operation:
ArrayList, Vector and Stack all implement get(i) using array subscripting and that is an O(1) operation.
LinkedList.get(i) involves i link traversals which is O(i). But if i is a constant, that reduces to O(1).
However there are other "built in" implementations of List. Indeed, there are a considerable number of them if you include the various non-public implementations, such as the List classes that implement sublists, unmodifiable lists, and so on. Generalizing from those 4 to "all of them" is not sound2.
But get(0) won't be O(1) for all possible implementations of List.
Consider a simple linked list where the elements are chained in the reverse order. Since get(0) needs to traverse to the end of the list, which is N link traversals: O(N).
Consider a list that is fully populated from the rows in a database query's result set the first time that you attempt to retrieve a list element. The first get call will be at least O(N) because you are fetching N rows. (It could be worse than O(N) if the database query is not O(N).) So the worst case complexity for any call to get is O(N) ... or worse.
Indeed, with a some ingenuity, one could invent a custom list where get(0) has any Big-O complexity that you care to propose.
1 - I am being deliberately vague here. On the one hand, we need to identify a variable N denoting the "problem" size for complexity analysis to make sense. (The length of the list is the obvious choice.) On the other hand, the length of a List is a surprisingly "rubbery" concept when you consider all of the possible ways to implement the interface.
2 - I assume that you are asking this question because you want to write some library code that relies on List.get(0) being O(1). Since you can't prevent someone from using your library with a non-builtin list implementation, your "assume it is builtin" constraint in your question doesn't really help ... even if we could check all possible (past, current or future) builtin List implementations for you.
Ignoring custom implementations, and only looking at built-in implementations, like suggested at the end of the question, you still cannot say that get(0) will be O(1) regardless of list size.
As an example, calling get(0) on a sublist based on a LinkedList will be O(n):
List<Integer> list = new LinkedList<>(Arrays.asList(1,2,3,4,5,6,7,8,9));
List<Integer> subList = list.subList(4, 8);
Integer num = subList.get(0); // <===== O(n), not O(1)
In that code, subList.get(0) internally calls list.get(4), which has O(n) time complexity.
Yes, for all implementations of List you mentioned get(0) is O(1).
As we know in Java each class that implements Collection interface should implement Iterator<E> iterator() method.
Stack and Queue are parts of collection hierarchy and implement this method as well. So we can write something like this:
Stack stack = new Stack();
// Deque stack = new ArrayDeque<>();
stack.add( "1" );
stack.add( "2" );
stack.add( "3" );
Iterator i = stack.iterator();
while ( i.hasNext() ) {
Object o = i.next();
if ( o.equals( "2" ) ) {
i.remove();
}
}
My concerns here are:
Is it ok that we are able to delete elements from the middle of the stack/queue?
Is it ok that stack/queue should "show" only one element (last in stack and first in queue) but actually we are able to get all of them without calling "pop","enqueue" methods?
In the strictest sense, Stack and Queue should not allow iteration over it's element but the only reason this restriction exists is to justify the existence of these data structures. As per sgi
Stack does not allow iteration through its elements.
This restriction is the only reason for stack to exist at all. Note that any Front Insertion Sequence or Back Insertion Sequence can be used as a stack; in the case of vector, for example, the stack operations are the member functions back, push_back, and pop_back. The only reason to use the container adaptor stack instead is to make it clear that you are performing only stack operations, and no other operations.
While some implementations follow this, for example std::stack in C++ does not expose iterator, other implementation provide iterators as a feature. Stack in java is built on top of Vector which implements iterator. Queue is built on top of Collection which requires iterator to be implemented. To answer your questions
Is it ok that we are able to delete elements from the middle of the stack/queue?
Yes. The underlying implementation will make sure that your stack/queue is in a consistent state after the deletion.
Is it ok that stack/queue should "show" only one element (last in stack and first in queue) but actually we are able to get all of them without calling "pop","enqueue" methods?
Yes it's a feature of the underlying implementation.
Is it ok that we are able to delete elements from the middle of the
stack/queue?
Yes since stack/queue both will keep their contract even after deleting , after all the methods exposed by stack/queue manipulate the internal implementation which is used for the deletion
Is it ok that stack/queue should "show" only one element (last in
stack and first in queue) but actually we are able to get all of them
without calling "pop","enqueu" methods?
Yes you are not violating either contract since the remove is done throw iterator interface of the element not queue or stack
As we know that stack is a data structure which follows LIFO order. And as per my knowledge stack allows to access top element only. But in Java we can use iterator with stack which somehow contradict the above idea of allowing access to only top element.
Sample code
Stack<Integer> s=new Stack<Integer>();
s.push(10);
s.push(20);
s.push(30);
------------------------------------------------------------------------
Iterator<Integer> itr=s.iterator();
while(itr.hasNext())
{
System.out.print(itr.next() + " "); // ouput:- 10 20 30
}
Now I have an iterator on stack which can traverse the stack in FIFO order and I can even delete any element by using itr.remove()
It's very confusing :)
Please explain...
PS: In case I use listIterator at the place of iterator then it's even more confusing because former one provides more methods.
Java Stack<T> provides more operations than the abstract stack data type. Most likely, this is done for historical reasons, because Stack has been part of Java 1.0, and its designers decided to derive it from Vector. This is how operations from Vector became operations on Stack. Once you allow additional public operations to a public class, there is no way to take them back.
This does not mean, however, that the class is somehow broken: if you do not want the additional operations provided by Vector<T>, do not use them in your code.
Are deques (double-ended queues) traversable data structures? Does it make a difference whether they are have an array-based implementation vs linked implementation?
Yes, deques is traversable data structure, you can get interator from deque for traversing. Functionally, It does not make difference. But, technically and data structure wise, it make a difference. Remember, when we are using list we can add node dynamically. But, when using array, we need to define the size of deque or default size is used. Now, if you insert another element then it will create new array of double size and copy old array into new array then insert the new element.
Yes, they are traversable. Especially in JAVA Deque API, you can always get either iterator (or) descendingIterator to traverse the Deque either from first to last (or) from last to first respectively.
For just traversing the Deque, the underlying implementation may not make much difference. But for other operations it does. People usually prefer ArrayDeque over LinkedList. For more information on this follow the thread Why is ArrayDeque better than LinkedList.
Also look at the corresponding JAVA APIs to get the major differences between these two different implementations.
No. Like the structures it is a hybrid of (i.e., stacks and queues), deques (or double-ended queues) are not designed to be traversable. In fact, they are specifically designed not to be traversable. If the capability of traversing items contained within is necessary for a particular application, then a dequeue is probably not the best data structure to use in that case.
I want to push some int to a priorityqueue but i can't! i used the queue.add() code but this code will return the sorted queue,please help,thank you!
A push/pop operation is clearly defined for a stack abstract data type; I'm not sure if it makes sense for a queue (or even a priority queue).
PriorityQueueimplementsQueue, which only specifies add/remove. On the other hand, a Deque has addFirst/Last, removeFirst/Last, etc. Perhaps one of these is what you're looking for.
An example
Here's an example of using a PriorityQueue of String, using a custom Comparator that compares lengths.
Queue<String> queue = new PriorityQueue<String>(
100, new Comparator<String>() {
#Override public int compare(String s1, String s2) {
return Integer.valueOf(s1.length()).compareTo(s2.length());
}
}
);
queue.add("Sally");
queue.add("Amy");
queue.add("Alice");
System.out.println(queue);
// "[Amy, Sally, Alice]"
System.out.println(queue.remove());
// "Amy"
System.out.println(queue.remove());
// "Alice"
queue.add("Tina");
System.out.println(queue.remove());
// "Tina"
As expected, the PriorityQueue will give the shortest String in the queue upon remove. Also as specified, ties are broken arbitrarily.
Related questions
On PriorityQueue
Java: How do I use a PriorityQueue?
In Java what should I use for a PriorityQueue that returns the greatest element first?
On Comparator and Comparable
When to use Comparable vs Comparator
Java: What is the difference between implementing Comparable and Comparator?
difference between compare() and compareTo()
Comparable and Comparator contract with regards to null
Why does the Java Collections Framework offer two different ways to sort?
The whole point of a priority queue is that it returns the smallest entry (or rather, the first element that'd appear in a sorted list) first. If that's not what you want, you probably don't want a straight PriorityQueue.
What you could do is create a class that has a PriorityQueue for the usual stuff, and a stack for "emergencies". Have a push(T) method that adds stuff to the stack, and an add(T) that adds to the queue. Whatever method gets the next element should remove it from the stack if there's anything there, else it gets the queue's next element.
I want to push some int to a
priorityqueue
'Push' is a stack operation, not a queue operation.
but i can't! i used the
queue.add() code but this code will
return the sorted queue
No it won't. A PriorityQueue is only sorted for the purposes of removing the head of the queue.
Your question doesn't make much sense. If you want to push, use a stack. If you don't want what a PriorityQueue does, don't use it.
What exactly is your actual problem?