public T removeMin() {
            T response = (T)store[1];

            //insert the last entry to the root if heap does not only contains root
            if(tail!=1){
                store[1] = store[tail];
            }
            //nullify the tail node since its copied to the root
            store[tail] = null;
            //reduce the tail
            tail --;

            int index = 1;
            // bubble down the root to satisfy heap order
            //check if root is bigger than left or right child
            while((index*2<=tail && (((T)store[index]).compareTo((T)store[index*2]) > 0)) || (index*2+1<=tail && (((T)store[index]).compareTo((T)store[index*2+1]) > 0)) ) {
                int minChildIndex = -1;
                T minChildValue = null;
                //if parent is bigger than left child
                if(((T)store[index]).compareTo((T)store[index*2]) > 0){
                    //assign minChildIndex and minChildValue of the left child
                    minChildIndex = index*2;
                    minChildValue = (T)store[minChildIndex];
                }
                //if right child is present, parent is bigger than the right child and the left child is even bigger then right child..
                // assign the right child to be the minimum one
                if(index*2+1 <=tail && ((T)store[index*2+1]).compareTo((T)store[index*2]) < 0 && ((T)store[index]).compareTo((T)store[index*2+1]) > 0){
                    //assign minChildIndex and minChildValue of the right child
                    minChildIndex = index*2 +1;
                    minChildValue = (T)store[minChildIndex];
                }
                //swap the parent with minimum child
                store[minChildIndex] = store[index];
                store[index] = minChildValue;
                index = minChildIndex;
            }
            return response;
        }