Resizable Array Implementation for Standard Generic Object Queue

Posted By : Neeraj Kumar | 16-Apr-2018

For Array implementation of a Standard Queue Data Structure, there are some key points we should keep in mind:

1. Randomly upsizing the array whenever the required size got larger than the actual size of the underlying array while enqueueing and

2. Randomly downsizing the  array whenever the actual size is much larger than the required size of the underlying array while de-queueing

 

Why are we doing these two required actions randomly and not regularly?

It's an obvious question one can ask and the answer is the performance optimization.

  • Lets first take the scenario of upsizing the underlying array: if we are upsizing the array whenever it's full, the order of growth for inserting first N elements will be proportional to 1+2+3+ ..... + N ~ N^2 / 2 which is a quadratic order of growth and hence it's unacceptable. So now we have to somehow randomize this upsizing of the array to reduce the order of growth of insert operation.
    The solution for this is repeated doubling, in which we double the size of the array when its full, which reduces the order of growth for inserting first N elements to N (not N^2).
  • Now the other problem from repeated doubling we have is that,  whenever we remove the element from queue we also need to maintain the size of the queue, we do not want to keep on increasing this size however we have empty spaces in our queue. Now we need to randomize the downsizing.
    Now you might be thinking why not to half the array just like we have doubled it for upsizing, but than if we half the array just when the size of queue is half of the size of array we will phase an order of growth N for enqueueing just the next element in queue and this will happen every time whenever an enqueue is performed just after the downsizing by dequeue, which is also bad. So to reduce this time complexity in downsizing by checking for the quarter size of the array to be equal to the size of the queue to half it at that point so we will not face the  N order growth for enqueueing just the next element in the queue.

     

public class ResizableArrayQueueOfObjects<T> {
    T[] s;
    int first = 0, last = 0;
    private int N = 0;
    
    public boolean isEmpty(){
        return N == 0;
    }
    public int size() {    
        return N;
    }
    @SuppressWarnings("unchecked")
    public ResizableArrayQueueOfObjects() {
        this.s = (T[]) new Object[1];
    }
    public void enqueue(T item) {
        if(s.length == N) {
            resize(first, last, 2 * s.length);
        }
        if(N != 0) {
            last += 1;
        }     
        s[last] = item;    //post increment of N    
        N = (last -first) + 1;        
    }
    //save us from thrashing
    public T dequeue() throws Exception {
        if(N > 0) {
            T item = s[first];
            N -= 1;
            s[first] = null;
            
            // Stoping first index from growing bigger than last index
            if(first < last){
                first += 1;
            }        
            if(s.length / 4 == 0) {
                if(N > 0 && N == s.length / 2) {
                    resize(first, last,  s.length / 2);
                }
            }
            if(N > 0 && N == s.length / 4) {
                resize(first, last,  s.length / 2);
            }
            return item;
        } else {
            throw new Exception("Queue already Empty!!");
        }
    }

    @SuppressWarnings("unchecked")
    private void resize(int first, int last, int capacity) {
        int oldLength = s.length;
        
        T[] copy = (T[]) new Object[capacity];
        for(int i = 0, j = first; j <= last; i++, j++) {
            copy[i] = s[j];
        }
        s = copy;
        //only for the down sizing
        if(s.length < oldLength) {
            this.first = 0;
            this.last = N-1;
        }
    }
    
    @Override
    public String toString() {
        String ss;
        
        ss = "[";
        for(int i = 0, j = first; j <= last; i++, j++) {
            ss = ss + s[j];
            if(s[j] != null) {
                if(((String) this.s[j]).length() != 0) {
                    ss = ss + ", ";
                }
            }
        }
        ss = ss + "]";
        return ss;
    }
}

Note: The  initial size of the underlying array is 1 and now when ever an element is enqueued the size increased with repeated doubling.

The Main Class, calling the ResizableArrayQueueOfObjects ADT(abstract data type).


public class Main {
    public static void main(String[] args) throws Exception {
        ResizableArrayQueueOfObjects<String> resizableArrayImpleOfQueue = new ResizableArrayQueueOfObjects<>();
      
        resizableArrayImpleOfQueue.enqueue("Hello World!");
        System.out.println(resizableArrayImpleOfQueue.toString());
        

        // repeadted doubling will occur to resize the array
        resizableArrayImpleOfQueue.enqueue("input 1");
        System.out.println(resizableArrayImpleOfQueue.toString());
        
        System.out.println(resizableArrayImpleOfQueue.dequeue());
        System.out.println(resizableArrayImpleOfQueue.toString());
        
        resizableArrayImpleOfQueue.enqueue("input 2");
        System.out.println(resizableArrayImpleOfQueue.toString());
        
        resizableArrayImpleOfQueue.enqueue("input 3");
        System.out.println(resizableArrayImpleOfQueue.toString());
        
        resizableArrayImpleOfQueue.enqueue("input 4");
        resizableArrayImpleOfQueue.enqueue("input 5");
        resizableArrayImpleOfQueue.enqueue("input 6");
        resizableArrayImpleOfQueue.enqueue("input 7");
        resizableArrayImpleOfQueue.enqueue("input 8");
        
        System.out.println(resizableArrayImpleOfQueue.toString());


        // repeated doubling will occur at this point to resize the array
        resizableArrayImpleOfQueue.enqueue("input 9");
        System.out.println(resizableArrayImpleOfQueue.toString());
        
        resizableArrayImpleOfQueue.enqueue("Hello yum!17");
        resizableArrayImpleOfQueue.enqueue("Hello yum!18");
        
        System.out.println(resizableArrayImpleOfQueue.dequeue());
        System.out.println(resizableArrayImpleOfQueue.toString());        
    }
}

 

About Author

Author Image
Neeraj Kumar

Neeraj is a JAVA Developer who possesses skill set in: Data Structures, Core Java, Java Enterprise Edition (Servlets, JSP, Standard Java Beans), Spring (Spring-core, spring-MVC, spring-Data-Access, Spring-Data-JPA), Hibernate, JPA, HTML, CSS, JavaScri

Request for Proposal

Name is required

Comment is required

Sending message..