How to get a particular element from Queue? - java

Unlike ArrayList, there is no get(int index) method in Queue to retrieve the element at specified position.
Anybody please tell me how to achieve this in Queue?
Thanks.

Accessing elements by index is not part of the concept of a queue.
If you need to access elements by index, you want a list, not a queue.

You can remove elements from the Queue until you reach the needed one. You can re-add the removed elements at the end of the queue or put them in a different queue (and add the rest after you reached the needed element).
You really shouldn't be using a Queue like that, though!
public static <T> T get(Queue<T> queue, int index) {
synchronized (queue) {
if (queue == null) {
return null;
}
int size = queue.size();
if (index < 0 || size < index + 1) {
return null;
}
T element = null;
for (int i = 0; i < size; i++) {
if (i == index) {
element = queue.remove();
} else {
queue.add(queue.remove());
}
}
return element;
}
}

public static Object retrieveElement(int index, Queue q) {
Iterator it = q.iterator();
int count = 0;
while (it.hasNext()) {
Object e = it.next();
if (count == index) {
it.remove();
return e;
}
count++;
}
return null;
}

public static <T> T getFromQueue(Queue<T> queue, int index){
if(index>=queue.size()){
throw new IndexOutOfBoundsException("index="+index+",size="+queue.size());
}
Queue<T> queueCopy = new LinkedList<T>(queue);
for(int i=0; i<index; i++){
queueCopy.remove();
}
return queueCopy.peek();
}

Queues operate in a first in first out (FIFO) manner therefore in order to access a particular element the elements must be removed and stored in a secondary queue until the element being searched for is identified

private static List<Individual> queueToList(Queue<Individual> archive) {
List<Individual> list = new LinkedList<Individual>();
Iterator<Individual> it = archive.iterator();
while(it.hasNext()){
list.add(it.next());
}
return list;
}

Basically the concept of Queue is FIFO(First In First Out).So accessing the particular index or the element in the queue is not possible. The other way is to get a particular element you need to delete it unless and until you get it.

Related

Removing element from array. Getting null instead of actually removing element/index

I'm trying to remove an element from an array. I am running into an issue where when I run my program and remove a certain index. I get nulls in the place where the element/index should be removed entirely.
My output is when I execute list.display() in the main method is
Tom, Bob, Richard
However after I execute list.remove() and run the program. I get
null, null, Richard.
Any tips?
public class MyArrayList implements MyList {
private Object[] theList;
public MyArrayList()
{
theList = new Object[0];
}
public boolean add(Object toAdd){
if(toAdd != null) {
Object[] temp = new Object[theList.length + 1];
for(int i = 0; i < theList.length; i++) {
temp[i] = theList[i];
}
temp[theList.length] = toAdd;
theList = temp;
return true;
} else {
return false;
}
}
public Object remove(int index) {
if (index >= 0 && index < theList.length) {
Object[] temp = new Object[theList.length - 1];
theList[index] = null;
int j = 0;
for (int i = 0; i < theList.length; i++) {
if (i == index) {
continue;
}
temp[j++] = theList[i];
theList = temp;
}
return temp;
}
return null;
}
public class Main {
public static void main(String[] args) {
MyArrayList list = new MyArrayList();
list.add("Tom");
list.add("Bob");
list.add("Richard");
list.display();
list.remove(0);
list.remove(1);
list.display();
}
}
Where you call list.remove(0), you should be assigning the result back to list again. For example:
list = list.remove(0);
A couple of other things:
It's generally a bad idea to change the index variable within a loop. It's legal, but leads to logic errors that can be difficult to reason about and diagnose.
You're getting the null in your output because the remove method also mutates the theList when you execute:
theList[index] = null;
Since you're returning a copy of theList you don't need to also set that element of the theList array to null.
Since your code implements MyList which is not available in code, i could not run below sample on your code but you can have below logic in your code. You don't need extra temp array in remove method. Since it an array, you can start traversing array from index which has to be removed and start moving next element by one step before.
public Object remove(int index) {
if (theList == null || index < 0 || index >= theList.length) {
return theList;
}
for (int i = index; i < theList.length; i++) {
theList[i] = theList[i + 1];
}
return null;
}
You can trim array tail if it has more empty places based on some threshold.
the code is doing exactly what you asked it to do. Those removed values are null because you have this line
theList[index] = null;
Also think about what your intentions are.
list.remove(0); <- this will remove the first element so now list would be Rob, Richard
list.remove(1); <- this will remove the 2nd element of the modified list (Rob, Richard) so result would be Rob. This is probably not what you want.
instead of this
if (i == index) {
i++; // risk of out of bounds exception
}
you probably want this instead
if (i == index) {
continue;
}

Implement Queue using fixed size array

I came across below interview question and I am working on it:
Build a queue class with the enqueue and dequeue methods. The queue
can store an UNLIMITED number of elements but you are limited to
using arrays that can store up to 5 elements max..
Here is what I was able to come up with. Is this the right way to do it in the interview or is there any better way we should implement in the interview?
class Solution {
private final List<List<Integer>> array;
public Solution() {
this.array = new ArrayList<>();
}
public void enqueue(int value) {
if(array.isEmpty()) {
List<Integer> arr = new ArrayList<>();
arr.add(value);
array.add(arr);
return;
}
if(array.get(array.size() - 1).size() != 5) {
array.get(array.size() - 1).add(value);
return;
}
List<Integer> arr = new ArrayList<>();
arr.add(value);
array.add(arr);
return;
}
public int dequeue() {
if(array.isEmpty()) {
return -1;
}
for(List<Integer> l : array) {
for(int i=0; i<l.size(); i++) {
return l.remove(i);
}
}
return -1;
}
}
As I mentioned in comments, your solution doesn't really solve the problem because the outer array of 5-element arrays can have more than 5 elements.
Instead, you can implement the queue as a linked list of 4-integer nodes, using the 5th element for a reference to the next array. But there's no reason to assume the elements are integers. This turns out to be pretty simple.
public class SillyQueue<T> {
private static final int MAX = 5;
private Object [] head = new Object[MAX], tail = head;
private int headPtr = 0, tailPtr = 0;
void enqueue(T x) {
if (tailPtr == MAX - 1) {
Object [] a = new Object[MAX];
tail[MAX - 1] = a;
tail = a;
tailPtr = 0;
}
tail[tailPtr++] = x;
}
T dequeue() {
if (headPtr == MAX - 1) {
head = (Object[]) head[MAX - 1];
headPtr = 0;
}
return (T) head[headPtr++];
}
}
Your answer uses ArrayList instead of true arrays, and worse, uses an unlimited arraylist to put those arrays in. I think that the interviewers expected you to implement a singly-linked list of 5-element arrays:
/**
* A singly-linked list node with an array; supports popping its 1st elements,
* and adding elements at the end, possibly by creating a new node
*/
public class ListNode {
final int MAX = 5;
private int contents[] = new int[MAX];
private int size = 0; // valid elements
private ListNode next = null;
private ListNode(ListNode next) {
this.next = next;
}
public boolean isEmpty() { return size == 0; }
public ListNode addLast(int value) {
ListNode next = this;
if (size == MAX) {
next = new ListNode(this);
}
next.contents[next.size ++] = value;
return next;
}
public int removeFirst() {
if (size == 0) {
throw new NoSuchElementException("empty queue");
}
int value = contents[0];
size --;
for (int i=1; i<size; i++) contents[i-1] = contents[i];
return value;
}
}
/**
* A simple queue on top of nodes that keep arrays of elements
*/
public class ListArrayQueue {
ListNode first = new ListNode();
ListNode last = first;
public void enqueue(int value) {
last = last.addLast(value);
}
public int dequeue() {
if (first.isEmpty() && first != last) {
first = first.next;
}
return first.removeFirst();
}
}
Performance-wise, this can be improved: you can avoid keeping the size in each ListNode, since only the 1st and last nodes can be non-full. You can also avoid the loop in removeFirst, but that would entail replacing size by firstIndex and lastIndex; which could again be moved into the ListArrayQueue to save space in each node.
If they has asked you to build an unlimited array out of 5-element array pieces, you would have had to implement something similar to a b-tree. Which, without handy references, would be quite hard to pull off during an interview.
You can use a 1-D array and use Wrap-around indexing to implement the queue with the limitation that queue can contain maximum 5 elements.
For checking the condition of empty queue, maintain a variable that counts the number of elements present in the queue.
Is this the right way to do it in the interview…?
Presenting uncommented code is never right, let alone in an interview.
In an interactive interview, it would be your task to find out whether you can/should use an unlimited number of arrays.
If not, you have to negotiate a way to handle an enqueue() to a queue filled to capacity in addition to a dequeue() to an empty one.
Fix the type of items the queue can hold.
Agree upon the parameters of the enqueue and dequeue methods.
The task is to Build a queue class, Solution is a bad choice for a name - array for something to access the items is no better.
In a language providing arrays, I'd take limited to using arrays literally - if using something more, why not an implementation of java.util.Queue?
The empty queue handling is entirely redundant: in enqueue(), you could have used
if (!array.isEmpty() && array.get(array.size() - 1).size() < 5); in dequeue() you can just drop it.
Instantiating List<Integer>s, you know there won't be more than five items at a time: tell the constructor.
dequeue() leaves empty List<Integer>s in arrays, giving rise to the current nested loop that desperately needs a comment.
(For the second part of the question, I second Rajkamal Tomar.)
Trade Off - Organize Fixed Size Arrays
Manage arrays based on ArrayList
enqueue - append new fixed size array - O(1)
dequeue - remove first fixed size array - O(n)
Manage arrays based on LinkedList
enqueue - append new fixed size array to linked list - O(1)
dequeue - remove first fixed size array - O(1)
cons - extra next pointer to setup linked list
public class FixedArrayQueue<T> {
private Node<T> head, tail;
private int front, rear, size;
private final int SIZE;
public FixedArrayQueue(int n) {
SIZE = n;
head = tail = new Node<T>(SIZE);
front = rear = size = 0;
}
public void enqueue(T t) {
tail.array[rear++] = t;
if (rear == SIZE) {
rear = 0;
append();
}
size++;
}
public T dequeue() {
if (size == 0) {
throw new EmptyQueueException();
}
T ret = head.array[front++];
if (front == SIZE) {
front = 0;
remove();
}
size--;
return ret;
}
private void append() {
tail.next = new Node<T>(SIZE);
tail = tail.next;
}
private void remove() {
head = head.next;
}
private boolean isEmpty() {
return size == 0;
}
private int size() {
return size;
}
}
class Node<T> {
T[] array;
Node<T> next;
public Node(int n) {
array = (T[]) new Object[n];
}
}

How to add items into an Array Generic Object from the parameter in Java

So, I am creating a generic data structure named "Sack". In this I add items to a sack, grab a random item, see if it's empty, or dump out its contents etc. Also I'm creating it to expand to hold as many items as needed.
Currently, I'm working on the add method and I'm having troubles on my add method, and I am trying to think of a way adding what's in my parameter into the sack.
import java.util.Arrays;
public class Sack<E>
{
public static final int DEFAULT_CAPACITY = 10;
private E [] elementData;
private int size;
#SuppressWarnings("unchecked")
public Sack()
{
elementData = (E[]) new Object[DEFAULT_CAPACITY];
}
#SuppressWarnings("unchecked")
public Sack(int capacity)
{
if(capacity < 0)
{
throw new IllegalArgumentException("capacity " + capacity);
}
this.elementData = (E[]) new Object[capacity];
}
public boolean isEmpty()
{
if(size == 0)
{
return true;
}
else
{
return false;
}
}
public E [] dump()
{
E [] E2 = Arrays.copyOf(elementData, size);
for(int i = 0; i < size; i++)
{
elementData[i] = null;
}
size = 0;
return E2;
}
In this method, I am trying to add item, into my sack. When I run my tests, I am told it's incorrect. If there's a way to improve this.
public void add(E item)
{
elementData[size] = item;
size++;
}
elementData is what I am adding the items into.
Update
I updated my add method to look like this.
public void add(E item)
{
if(size >= elementData.length-1)
{
elementData[size] = item;
size++;
}
}
The message I am now receiving is that add is not working correctly and to check size usage.
You cannot ensure capacity of Java arrays, Javascript can! You can create a new one and copy:
public void add(E element) {
int index = size++;
if(size >= elementData.length-1) {
// it ensures elementData
elementData = java.util.Arrays.copyOf(elementData, size);
}
elementData[index] = element;
}
or skip ensure of array capacity and change the check direction:
public void add(E element) {
if(size < elementData.length-1) {
elementData[size++] = element;
}
// TODO else notice of the unsuccessfull add
}
It sounds like there's a spec for what your Sack is supposed to do that you did not paste.
It also sounds like your add method is supposed to just work, even if the sack is already at capacity.
That means you need to make a new array, copy over all elements, and then replace the array you have in your Sack instance with the new one (because java arrays cannot grow or shrink).
Look at the source of of java's own ArrayList for a hint on how that's done.
So after numerous tries, I give credit to #rockfarkas for solving this. I put in the following code and it solved my add method code.
public void add(E item)
{
int index = size++;
if(size >= elementData.length-1)
{
elementData = Arrays.copyOf(elementData, size);
}
elementData[index] = item;
}
Here's another way of doing this,
public void add(E item)
{
ensureCapacity(size+1);
elementData[size] = item;
size++;
}
This also works, but I would have to modify the ensureCapacity method accurately, which I have.

Adding a value at an index in an array list

I need to make my own data structures and part of this is doing an ArrayList. I need to make sure I can add an object at element n while pushing all the others down. Here is my code. Right now it is adding the element twice. It is the function public ReturnObject add(int index, Object item). I need this function to add the object at the specified index and then shift the others down.
public class ArrayList implements List{
public static final int CAPACITY=16;
private int size = 0;
private Object[] data;
ReturnObjectImpl ro;
//constructors
public ArrayList() {
data = new Object[CAPACITY];
} //CONSTRUCTS LIST WITH DEFAULT CAPACITY
public ArrayList(int capacity) { // constructs list with given capacity
data = new Object[capacity];
System.out.println("Created an ArrayList of capacity " + capacity);
}
public boolean isEmpty(){
if(size == 0) {
// System.out.println("The list is empty");
return true;
}
return false;
}
public int size(){
System.out.println("The ArrayList is not full, but currently has " + size + " indexs");
return size;
}
public ReturnObject get(int index){
ro = new ReturnObjectImpl(data[index]);
return ro;
}
public ReturnObject remove(int index){
return null;
}
public ReturnObject add(int index, Object item){
if(index <= size && index < data.length){
for (int x = size-1; x >= index; x--){
data[x+1] = data[x];
data[index] = item;
ro = new ReturnObjectImpl(data[index]);
size++;
}
System.out.println("Added to array at " + index);
}
return ro;
}
public ReturnObject add(Object item){
if (data[0] == null){
data[0] = item;
}
//int adding = size + 1;
data[size] = item;
System.out.println("Added item to index " + size);
size++;
return null;
}
//added - but DELETE BEFORE SUBMITTING
public void printAll(){
for(int x = 0; x < data.length; x++){
System.out.println(data[x]);
}
}
}
Obviously, when inserting an object into that array:
for (int x = size-1; x >= index; x--){
data[x+1] = data[x];
data[index] = item;
that should not happen within a loop! Insertion should happen exactly once, at the correct index! So even when you keep that loop to move the other elements, that last assignment should go after that "moving loop" is over.
So the point is: you should step back and carefully look what this loop is doing with its loop variable.
In other words: either take a piece of paper and "run" the code yourself; or run it in a debugger.
As this is probably some kind of homework activity, I will leave it with that; it should be really enough to get you going and help you fix your code.
In addition to GhostCat's answer, instead of a for loop, you can just use System.arrayCopy() to 'move' the right part to the right. You only need to know whether your internal array (data) is already full or not. If it is, then you must expand the internal array.
System.arraycopy(this.data, insertIndex, this.data, insertIndex + 1, 1);
Some notes:
The code
if (data[0] == null) {
data[0] = item;
}
will throw an ArrayIndexOutOfBoundsException if ArrayList(0) was called.
The code
if (size == 0) {
// System.out.println("The list is empty");
return true;
}
return false;
can be rewritten to
return (size == 0);
You seem to omit more checks, like the check whether the internal array is full or not. Your current code does not expand the internal array, so if one ever adds more objects than the initial capacity (default 16), then an ArrayIndexOutOfBoundsException is thrown.

Program throwing an exception after I check for the exception

I must be missing something very simple because this is blowing my mind!
I am trying to implement a Heap using a CompleteBinaryTree (which is implemented using an array). This CompleteBinaryTree is an array of Position<T> where each Position holds an element. I am writing the add(T t) method for the Heap, where t is inserted into the next free position of the CompleteBinaryTree, and then an upheap process is performed until the CompleteBinaryTree is ordered. Here is the method:
private CompleteBinaryTree<T> tree = new CompleteBinaryTree<T>();
private Position<T> entry = null;
public void add(T t) {
entry = tree.add(t);
if (entry.equals(tree.root())) {
return;
}
//continue to swap inserted element with its parent
//while it is smaller than its parent
while (entry.element().compareTo(tree.parent(entry).element()) < 0) {
Position<T> parent = tree.parent(entry);
Position<T> temp = entry;
entry = parent;
parent = temp;
}
}
The first element is added fine into the Heap, but when I try to add the second element, an InvalidPositionException is thrown at the while() line. This is where the exeption is being thrown from inside the CompleteBinaryTree class:
public Position<T> parent(Position<T> p) {
if (p == root()) throw new InvalidPositionException();
return array[((ArrayPosition) p).index/2];
}
And here are the two other methods used from CompleteBinaryTree:
public Position<T> root() {
if (isEmpty()) throw new InvalidPositionException();
return array[1];
}
public Position<T> add(T t) {
if (last == array.length) {
// extend array
ArrayPosition[] temp = (ArrayPosition[]) new Object[array.length*2];
for (int i=1; i < array.length; i++) {
temp[i] = array[i];
}
array = temp;
}
array[last] = new ArrayPosition(last, t);
return array[last++];
}
How am I getting an exception thrown because p == root(), when I first check if p is the root?
EDIT
Here is the CompleteBinaryTree toString(), which is returned by the Heap toString():
public String toString() {
StringBuffer buf = new StringBuffer();
for (int i = 1; i < last; i++) {
buf.append(" ").append(array[i]);
}
return buf.toString();
}
How am I getting an exception thrown because p == root(), when I first check if p is the root?
But you do not check every tree.parent() argument to see whether it is root. You check only the argument passed to the first invocation of that method. Every time the body of the while loop is executed, it sets entry to a new value, and when the loop cycles you pass that new, unchecked, value to tree.parent(). Indeed, each new value of entry is closer to the root than the previous one, because the whole point is to move up the tree from child to parent, i.e. toward the root. It is entirely likely that sometimes this procedure will reach the root, and that's more likely the fewer elements are already in the tree.
One way to solve this would be to move the root-check into the while condition:
while (!entry.equals(tree.root())
&& entry.element().compareTo(tree.parent(entry).element()) < 0) {
// ...
}
In that case, of course, you do not need the current one-time check that you perform outside the loop.

Categories