Implementing a queue in Java is pretty common interview question. I surfed online and saw many implementations where they do fancy stuff like implementing queue interface and writing own addLast() and removeFirst() methods. My question is can't I just use LinkedList() class and use its predefined methods addLast and removeFirst methods to do the same??
e.g.
LinkedList<Student> qu=new LinkedList<Student>();
qu.add(new Student("anadkat1"));
qu.add(new Student("anadkat2"));
qu.add(new Student("anadkat5"));
System.err.println(qu);
qu.removeFirst();
System.err.println(qu);
This is giving me the perfect result. Isn't this enough?
public class Queue<T>{
private LinkedList<T> list=new LinkedList<>();
public void insert(T element){
list.addLast(element);
}
public void remove(){
list.removeFirst();
}
public int size(){
return list.size();
}
public T element(){
return list.getFirst();
}
}
I have very recently gone through these kind of interview questions.
Using set methods to add,remove, chekForEmpty etc from a list is a general way to implement a queue.
for example :
public void enqueue(E item) {
list.addLast(item);
}
public E dequeue() {
return list.poll();
}
public boolean hasItems() {
return !list.isEmpty();
}
public int size() {
return list.size();
}
public void addItems(GenQueue<? extends E> l) {
while (l.hasItems())
list.addLast(l.dequeue());
}
One way is to maintain an array of items q and two indices to the head and the tail of the queue (initially set to 0). Pseudo-code follows:
enqueue(x)
{ q[tail++] = x;
}
dequeue()
{ return q[head++];
}
If the array overflows, you double the size and reinsert the items. This yields O(1) amortized time per operation. Another approach is to use a linked list (which you should implement) and again store a pointer to the head and a pointer to the tail.
Related
I've been tasked with the following question: create a collection ReverseList that would implement List. by iterating over an object list of type ReverseList with a for loop (for(E e:list)) we would get the items in an order reversed of what they were entered.
implement the following class while extending from ArrayList
so essentially I need to create a collection that doesnt follow the natural ordering of insertion
let me clarify that i am not looking to reverse the list after its creation and adding items with something like Collections.reverse() but rather have the list maintain its own order
what I've tried so far is making a custom Iterator. however for some reason when trying to iterate over the list im getting thrown out with an IndexOutOfBoundsException (even though the list isnt empty)
my code:
public class ReverseList<E> extends ArrayList<E> implements List<E>{
private class ReverseIterator<E> extends ReverseList<E> implements Iterator<E>
{
private int pos;
public ReverseIterator()
{
pos = super.size()-1;
}
public ReverseIterator(ReverseList<E> r)
{
pos = r.size()-1;
}
#Override
public boolean hasNext() {
return pos >= 0;
}
#Override
public E next() {
return super.get(pos--);
}
}
#Override
public Iterator<E> iterator() {
// TODO Auto-generated method stub
return new ReverseIterator<E>(this);
}
public static void main(String[] args)
{
ReverseList<Integer> r = new ReverseList<>();
r.add(new Integer(1));
r.add(new Integer(2));
r.add(new Integer(3));
r.add(new Integer(4));
for(Integer i:r)
{
System.out.println(i);
}
}
}
error thrown: Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 0 ( thrown at the for loop )
why is the list at length 0?
is my approach even possible? is there a better way to do it?
Your ReverseIterator is a subclass of ReverseList. This means, it is a list on its own. Then, you are mixing up the state of these two lists. In the ReverseIterator(ReverseList<E> r), you use r’s size to initialize pos, in next() you use super.get(pos--), accessing the other list’s content. This other list is always empty.
An iterator should never be a collection. When you implement an iterator as an inner class, you can access the outer collection’s state implicitly.
Besides that, your list clearly violates the contract of the List interface and will cause a lot of other problems in the future, as its iterator() is inconsistent with other List features, like all index based operations or listIterator().
You should not change the fundamentals of a class, just for the sake of a single operation (i.e. iterate backwards). Rather, implement this single operation as a distinct operation.
For example:
public class ReversibleList<T> extends ArrayList<T> {
private class ReverseIterator implements Iterator<T> {
private int pos = size() - 1;
#Override
public boolean hasNext() {
return pos >= 0;
}
#Override
public T next() {
return get(pos--);
}
}
public Iterable<T> reverse() {
return () -> new ReverseIterator();
}
public static void main(String[] args) {
ReversibleList<Integer> r = new ReversibleList<>();
r.add(1);
r.add(2);
r.add(3);
r.add(4);
for(Integer i: r.reverse()) {
System.out.println(i);
}
}
}
The reverse() view has no storage of its own but always reflects the current contents of the list, in reverse order. The original List keeps fulfilling its contract.
Note that it is possible to create reversed view to a list supporting other operations of the List interface beyond iterator():
public class ReversibleList<T> extends ArrayList<T> {
private class ReversedList extends AbstractList<T> implements RandomAccess {
#Override
public T get(int index) {
return ReversibleList.this.get(size() - index - 1);
}
#Override
public int size() {
return ReversibleList.this.size();
}
}
public List<T> reverse() {
return new ReversedList();
}
public static void main(String[] args) {
ReversibleList<Integer> r = new ReversibleList<>();
r.add(1);
r.add(2);
r.add(3);
r.add(4);
r.reverse().subList(1, 4).stream().forEach(System.out::println);
}
}
I want to do the same thing I did in this code for stack
how can i change it so it will be for queue? I don't want to use stack or LinkedList for that
public StackAsArray(){
this(new DynamicArray());
}
public boolean isEmpty() {
}
public void push(Object o) {
}
public Object pop() {
}
}
You just need to replace your push and pop methods with enqueue and dequeue methods.
enqueue adds elements to the end of the array, while dequeue will remove it from the beginning.
public class QueueAsArray implements Queue {
...
public void enqueue(Object o) {
arr.set(numOfElements, o);
numOfElements++;
}
public Object dequeue() {
if(isEmpty()) { // an empty check is a MUST
return null;
}
numOfElements = numOfElements - 1;
Object res = arr.get(0);
arr.set(0, null); // not 100% sure this works, but since this is a homework question, its upto you to figure out. The logic is to remove the 0th element.
return res;
}
}
This is a classic implementation of an immutable linked list:
public abstract class List<A> implements Iterable<A> {
private static final List NIL = new Nil();
public abstract A head();
public abstract List<A> tail();
public List<A> cons(A a) { return new Cons<>(a, this); }
public static <A> List<A> nil() { return NIL; }
#Override
public Iterator<A> iterator() {
return new Iterator<A>() {
private List<A> list = List.this;
#Override
public boolean hasNext() {
return list != NIL;
}
#Override
public A next() {
A n = list.head();
list = list.tail();
return n;
}
};
}
public Stream<A> stream() {
return StreamSupport.stream(spliterator(), false);
}
public Stream<A> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}
class Nil extends List {
#Override public Object head() { throw new NoSuchElementException(); }
#Override public List tail() { throw new NoSuchElementException(); }
}
class Cons<A> extends List<A> {
private final A head;
private final List<A> tail;
Cons(A head, List<A> tail) {
this.head = head;
this.tail = tail;
}
#Override public A head() { return head; }
#Override public List<A> tail() { return tail; }
}
The default implementation of spliterator() does not support efficient parallelizing:
List<Integer> list = List.<Integer> nil().cons(3).cons(2).cons(1);
list.parallelStream().forEach(i -> {
System.out.println(i);
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
});
This will print 1, 2, 3 sequentially.
How to implement spliterator() to support efficient parallelizing?
The spliterators which cannot report even the estimated size (which is default implementation for Iterable) are poorly split by parallel pipeline. You can fix this issue if you track the size of the List. In your case it's not very hard to track the exact size:
public abstract class List<A> implements Iterable<A> {
...
public abstract long size();
#Override
public Spliterator<A> spliterator() {
return Spliterators.spliterator(iterator(), size(), Spliterator.ORDERED);
}
}
class Nil extends List {
...
public long size() {
return 0;
}
}
class Cons<A> extends List<A> {
...
private final long size;
Cons(A head, List<A> tail) {
this.head = head;
this.tail = tail;
this.size = tail.size()+1;
}
...
#Override
public long size() {
return size;
}
}
After that parallelization would work better. Note that it's still poor man parallelization, because you cannot quickly jump to the middle of the list, but in many cases it will provide a reasonable speed-up.
Also note that it's better to explicitly specify the Spliterator.ORDERED characteristic. Otherwise the order may be ignored in parallel stream operations even if it's explicitly requested (for example, by forEachOrdered() terminal operation).
You might use some algorithm with interleaving - e.g., counting the elements and using remainder after integer division. That could split the elements for parallel iteration.
You could also iterate once before the iterator is even constructed, to split the list into intervals, but that would beat the purpose of stream - e.g. if you use it for anyMatch, it will slow you a lot.
There is no really efficient way to split a linked list (in less than linear time), unless you create your own implementation of linked list that has some additional information.
Edit: Oh wait - you only implement Iterable. That is quite limiting, you have to come up with an algorithm that only has one pass. That means, the splitting itself won't be parallel at all, so you might as well enforce your parallelism elsewhere in the process.
I am working (in Java) on a recursive image processing algorithm that recursively traverses the pixels of the image, outwards from a center point.
Unfortunately, that causes a Stack Overflow. So I have decided to switch to a Queue-based algorithm.
Now, this is all fine and dandy- but considering the fact that its queue will be analyzing THOUSANDS of pixels in a very short amount of time, while constantly popping and pushing, WITHOUT maintaining a predictable state (It could be anywhere between length 100, and 20000), the queue implementation needs to have significantly fast popping and pushing abilities.
A linked list seems attractive due to its ability to push elements onto itself without rearranging anything else in the list, but in order for it to be fast enough, it would need easy access to both its head, AND its tail (or second-to-last node if it were not doubly-linked). Sadly, I cannot find any information related to the underlying implementation of linked lists in Java, so it's hard to say if a linked list is really the way to go...
This brings me to my question. What would be the best implementation of the Queue interface in Java for what I intend to do? (I do not wish to edit or even access anything other than the head and tail of the queue -- I do not wish to do any sort of rearranging, or anything. On the flip side, I DO intend to do a lot of pushing and popping, and the queue will be changing size quite a bit, so preallocating would be inefficient)
Use:
Queue<Object> queue = new LinkedList<>();
You can use .offer(E e) to append an element to the end of the queue and .poll() to dequeue and retrieve the head (first element) of the queue.
Java defined the interface Queue, the LinkedList provided an implementation.
It also maintains references to the Head and Tail elements, which you can get by .getFirst() and .getLast() respectively.
credit to #Snicolas for suggesting queue interface
If you use LinkedList be careful. If you use it like this:
LinkedList<String> queue = new LinkedList<String>();
then you can violate queue definition, because it is possible to remove other elements than first (there are such methods in LinkedList).
But if you use it like this:
Queue<String> queue = new LinkedList<String>();
it should be ok,as this is heads-up to users that insertions should occur only at the back and deletions only at the front.
You can overcome defective implementation of the Queue interface by extending the LinkedList class to a PureQueue class that throws UnsupportedOperationException of any of the offending methods. Or you can take approach with aggreagation by creating PureQueue with only one field which is type LinkedList object, list, and the only methods will be a default constructor, a copy constructor, isEmpty(), size(), add(E element), remove(), and element(). All those methods should be one-liners, as for example:
/**
* Retrieves and removes the head of this queue.
* The worstTime(n) is constant and averageTime(n) is constant.
*
* #return the head of this queue.
* #throws NoSuchElementException if this queue is empty.
*/
public E remove()
{
return list.removeFirst();
} // method remove()
Check out the Deque interface, which provides for insertions/removals at both ends. LinkedList implements that interface (as mentioned above), but for your use, an ArrayDeque may be better -- you won't incur the cost of constant object allocations for each node. Then again, it may not matter which implementation you use.
Normal polymoprhism goodness comes to play: the beauty of writing against the Deque interface, rather than any specific implementation of it, is that you can very easily switch implementations to test which one performs best. Just change the line with new in it, and the rest of the code stays the same.
It's better to use ArrayDeque instead of LinkedList when implementing Stack and Queue in Java. ArrayDeque is likely to be faster than Stack interface (while Stack is thread-safe) when used as a stack, and faster than LinkedList when used as a queue. Have a look at this link Use ArrayDeque instead of LinkedList or Stack.
If you know the upper bound of possible quantity of items in the queue, circular buffer is faster than LinkedList, as LinkedList creates an object (link) for each item in the queue.
I think you can some up with simple like implementation
package DataStructures;
public class Queue<T> {
private Node<T> root;
public Queue(T value) {
root = new Node<T>(value);
}
public void enque(T value) {
Node<T> node = new Node<T>(value);
node.setNext(root);
root = node;
}
public Node<T> deque() {
Node<T> node = root;
Node<T> previous = null;
while(node.next() != null) {
previous = node;
node = node.next();
}
node = previous.next();
previous.setNext(null);
return node;
}
static class Node<T> {
private T value;
private Node<T> next;
public Node (T value) {
this.value = value;
}
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setNext(Node<T> next) {
this.next = next;
}
public Node<T> next() {
return next;
}
}
}
However, if you still want to use the recursive algorithm, you can change it to be "tail-recursive" which probably is optimized in the JVM to avoid stack overflows.
O(1) access to first and last nodes.
class Queue {
private Node head;
private Node end;
public void enqueue(Integer data){
Node node = new Node(data);
if(this.end == null){
this.head = node;
this.end = this.head;
}
else {
this.end.setNext(node);
this.end = node;
}
}
public void dequeue (){
if (head == end){
end = null;
}
head = this.head.getNext();
}
#Override
public String toString() {
return head.getData().toString();
}
public String deepToString() {
StringBuilder res = new StringBuilder();
res.append(head.getData());
Node cur = head;
while (null != (cur = cur.getNext())){
res.append(" ");
res.append(cur.getData());
}
return res.toString();
}
}
class Node {
private Node next;
private Integer data;
Node(Integer i){
data = i;
}
public Integer getData() {
return data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
Here is the Queue Implementation with Iterator and Iterable interface
Queue Size will increase as It gets full
Queue Interface
package com.practice.ds.queue;
import com.practice.ds.queue.exception.QueueException;
public interface QueueInterface<T> {
public boolean empty();
public void enqueue(T item);
public void dequeue() throws QueueException;
public T front() throws QueueException;
public void clear();
}
Custom Exception Class
package com.practice.ds.queue.exception;
public class QueueException extends Exception {
private static final long serialVersionUID = -884127093599336807L;
public QueueException() {
super();
}
public QueueException(String message) {
super(message);
}
public QueueException(Throwable e) {
super(e);
}
public QueueException(String message, Throwable e) {
super(message, e);
}
}
Implementation of Queue
package com.practice.ds.queue;
import java.util.Iterator;
import com.practice.ds.queue.exception.QueueException;
public class Queue<T> implements QueueInterface<T>, Iterable<T> {
private static final int DEFAULT_CAPACITY = 10;
private int current = 0;
private int rear = 0;
private T[] queueArray = null;
private int capacity = 0;
#SuppressWarnings("unchecked")
public Queue() {
capacity = DEFAULT_CAPACITY;
queueArray = (T[]) new Object[DEFAULT_CAPACITY];
rear = 0;
current = 0;
}
#Override
public boolean empty() {
return capacity == current;
}
#Override
public void enqueue(T item) {
if(full())
ensureCapacity();
queueArray[current] = item;
current++;
}
#Override
public void dequeue() throws QueueException {
T dequeuedItem = front();
rear++;
System.out.println("Dequed Item is " + dequeuedItem);
}
#Override
public T front() throws QueueException {
return queueArray[rear];
}
#Override
public void clear() {
for (int i = 0; i < capacity; i++)
queueArray[i] = null;
current = 0;
rear = 0;
}
#SuppressWarnings("unchecked")
private void ensureCapacity() {
if (rear != 0) {
copyElements(queueArray);
} else {
capacity *= 2;
T[] tempQueueArray = (T[]) new Object[capacity];
copyElements(tempQueueArray);
}
current -= rear;
rear = 0;
}
private void copyElements(T[] array) {
for (int i = rear; i < current; i++)
array[i - rear] = queueArray[i];
queueArray = array;
}
#Override
public Iterator<T> iterator() {
return new QueueItearator<T>();
}
public boolean full() {
return current == capacity;
}
private class QueueItearator<T> implements Iterator<T> {
private int index = rear;
#Override
public boolean hasNext() {
return index < current;
}
#SuppressWarnings("unchecked")
#Override
public T next() {
return (T) queueArray[index++];
}
}
}
I need some container to keep elements so, if I'll try to get the size()+i element, i'll get element number i. Or with iterator, which starts from the beginning of container after it tries to get the last element? What are the best practicies in both cases? I mean performance and easy useability.
You could create a simple subclass of ArrayList<T> and override the get(int n) method as follows:
public T get(int n)
{
return super.get(n % this.size());
}
As to the iterator, you will need to implement your own, which shouldn't be all that hard.
EDIT:
Assuming your new class is called RingList, here's a sample RingIterator (untested):
public class RingIterator<T> implements Iterator<T>
{
private int cur = 0;
private RingList<T> coll = null;
protected RingIterator(RingList<T> coll) { this.coll = coll; }
public boolean hasNext() { return size() > 0; }
public T next()
{
if (!hasNext())
throw new NoSuchElementException();
int i=cur++;
cur=cur%size();
return coll.get(i);
}
public void remove() { throw new UnsupportedOperationException(); }
}
You would then override the iterator() method in RingList<T> as
public Iterator<T> iterator()
{
return new RingIterator(this);
}
For the first part, just ask for n % list.size() perhaps?
For the iterator part, create a class that wraps an iterator, and when next() returns null, just have it reset the iterator.
Thanks everyone, thats what I've created:
public class RingIterator<E> {
private List<E> _lst;
private ListIterator<E> _lstIter;
public RingIterator(ListIterator<E> iter, List<E> lst) {
super();
_lstIter = iter;
_lst = lst;
}
public E next() {
if(!_lstIter.hasNext())
_lstIter = _lst.listIterator();
return _lstIter.next();
}
public E previous() {
if(!_lstIter.hasPrevious())
_lstIter = _lst.listIterator(_lst.size());
return _lstIter.previous();
}
}
Then get method:
/*
* Returns ring iterator,
* use it with 'ParentClass' type.
*/
public RingIterator<SubClass> getRingIter(int i) {
return new RingIterator(_subs.listIterator(i),_subs);
}
And I use it:
RingIterator<SubClass> ri = _logic.getRingIter(1);
ParentClass ai = ri.next();
I wanted to make only type ParentClass (not SubClass) available via getRingIter, but I don't see a way to do it with no creation of List - convertion of List.
Extend the ArrayList class and implement the get(Integer) method the way you like. I think this is the 'best practice'.