I have a program where I am creating an arrayList. One method randomly removes an item from the list. I also have a method that resizes the array if a certain amount of elements are added to make space for more elements to be added if wanted.
I am receiving a NullPointerExceptionError when the lists are resized and then the method tries to remove one of the null spaces in the newly resized array.
Without using a for loop and keeping a constant time, I'm trying to find a way to make my int value of choice just the number of non null elements in the array. I hope that makes sense - can anyone help?
remove method:
public T remove() {
if (isEmpty()) {
return null;
}
Random rand = new Random();
int choice = rand.nextInt(size);
size--;
elements[choice] = elements[size];
elements[size] = null;
return elements[choice];
}
This question boils down to "Given an array with null elements scattered throughout, how can I return the nth non-null element?" The answer is iterate through the array, which doesn't uphold the constant time constraint your're looking for.
But wait, how can array lists work in that case?!?
Here is how java.util.ArrayList does it:
#Override
public E get(int location) {
if (0 <= location && location < (lastIndex - firstIndex)) {
return (E) array[firstIndex + location];
}
throw new IndexOutOfBoundsException(Messages.getString("luni.0A",
location, lastIndex - firstIndex));
}
Note that there are no null checks, the Arraylist always maintains its elements in a contiguous block so gets are super fast. So some magic must happen when removing elements so there won't be nulls scattered about...
#Override
public E remove(int location) {
E result;
int localLastIndex = lastIndex;
int size = localLastIndex - firstIndex;
if (0 <= location && location < size) {
if (location == size - 1) {
result = (E) array[--localLastIndex];
array[localLastIndex] = null;
} else if (location == 0) {
result = (E) array[firstIndex];
array[firstIndex++] = null;
} else {
int elementIndex = firstIndex + location;
result = (E) array[elementIndex];
if (location < size / 2) {
System.arraycopy(array, firstIndex, array, firstIndex + 1,
location);
array[firstIndex++] = null;
} else {
System.arraycopy(array, elementIndex + 1, array,
elementIndex, size - location - 1);
array[--localLastIndex] = null;
}
}
if (firstIndex == localLastIndex) {
firstIndex = localLastIndex = 0;
}
} else {
throw new IndexOutOfBoundsException(Messages.getString("luni.0A",
location, localLastIndex - firstIndex));
}
lastIndex = localLastIndex;
modCount++;
return result;
}
There is the key! When removing an element the JDK impl doesn't leave a gap, nor does it move all the elements over to close the gap. It calls a native method that copies a chunk of array around as an atomic operation: https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#arraycopy(java.lang.Object,%20int,%20java.lang.Object,%20int,%20int)
Related
I am trying to build the following method for my extended stack ADT implemented using a doubly linked list method is called
public T pop(int i) throws InvalidItemException.
It should remove and return the i-th data item from the top of the stack. for example if i = 1 it would return and remove the top item of the stack, if i = 3 then it would take the third item from the top.
this is my code it is a bit of a mess but I think I am somewhat on the right track. Can anyone help with this?
public T pop(int i) throws InvalidItemException {
int node = size() + 1; // my logic is that if i take the length and add 1
int nodeRemove = node - i; // and then minus the length by i then i will know which item to take
DoubleLinkedNode<T> temp = top;
T result = null;
if (i > numItems || i <= 0) {
throw new InvalidItemException("invalid items");
}
if (i == 1) {
top = top.getNext();
result = top.getElement();
}else {
while (temp != null && nodeRemove > 1) {
temp = temp.getNext();
result = temp.getElement();
nodeRemove--;
}
}
return result;
I am creating a class that has an array, and I want to implement methods add, remove, and replace.
But I don't want to use any built-in internals.
public class MySet {
public int set[];
private int size = 0;
public MySet(int size) {
this.set = new int[size];
}
public boolean add(int item) {
for (int i = 0; i < this.size(); i++) {
if (this.set[i] != 0) {
// add to array
}
}
this.size++;
return true;
}
public int size()
{
return this.size;
}
}
When you initialize an array with a fixed size in Java, each item is equal to 0. The part with if this.set[i] != 0 is where I am stuck to add an item.
Should I use a while loop with pointers? Such as:
public boolean add(int item) {
int index = 0;
while (index <= this.size()) {
if (this.set[index] != 0 || index <= ) {
// increase pointer
index++;
}
this.set[index] = item;
}
But if I have an array such as [7, 2, 0 , 1] in the list, it won't get the last item in the loop, which I need.
So, how is this usually done?
You should keep the current index for the size of populated elements which looks like you do. When you add the set[size]= item and increment size. Once size hits the preallocated size of your array you need to create a new array with increased size (can pick double the size for example) and copy old array to the new one.
I am beginner in Java and trying to write a StackArray. I have a tester to test my code. I have run it several times but it does not pass my push method and my search method. Can anyone give me an idea where I am doing wrong? Thank you so much in advance!
import java.util.Arrays;
import java.util.NoSuchElementException;
public class Stack<E> implements StackADT<E>{
private E a[];
private int head, size;
public Stack(){
}
/*Adds the specified element to the top of the stack.
Returns the item added.*/
public E push(E element){
if (a.length == size){
throw new IllegalStateException("Cannot add to full stack");
}
// Since the remainder of the stack is to the RIGHT of the stack,
// adding a new element pushes the head to the LEFT (+ wrap around)
//head = (head - 1 + a.length) % a.length;
return a[head++] = element;
// return element;
}
/*Removes and returns the element from the top of the stack*/
public E pop(){
if (empty()){
throw new java.util.EmptyStackException();
}
// We need to get a copy of the old head before we advance to the
// new head. We want to return the old head, not the new head.
E rval = a[head];
// Why DON'T we need to add a.length here like we did in push?
head = (head + 1) % a.length;
return rval;
}
/*Returns without removing the element at the top of the stack*/
public E peek(){
if (empty()){
throw new java.util.EmptyStackException();
}
return a[head];
}
/*Returns true if the stack is empty, false otherwise*/
public boolean empty(){
return size == 0;
}
/*Returns the 1-based position where an object is on this stack
This means If the object o occurs as an item in this stack, this
method returns the distance FROM THE TOP OF THE STACK of the
occurrence nearest the top of the stack - the topmost item on
the stack is considered to be at distance 1.*/
public int search(Object o){
// i is the LOGICAL index
for (int i = 0; i < size; i++){
// p is the PHYSICAL index
int p = (head + i) % a.length;
E e = a[p];
// e == o Are the items (null or non-null the same?)
// if they are not the same, then at least one of them
// is non-null and can be compared to the other.
if (e == o || e != null && e.equals(o)){
// Distance = logical index + 1 as per the above description
return i + 1;
}
}
// No match was made
throw new NoSuchElementException();
}
/*Returns a string representation of the queue*/
public String toString(){
// Output should look like: [e_0, e_1, ..., e_n-1]
// Empty stack: []
if (empty())
return "[]";
// We know that there is at least one element in this stack
// since we didn't return
StringBuilder b = new StringBuilder();
b.append("[").append(a[head]);
// Start on the SECOND logical index
for (int i = 1; i < size; i++){
int p = (head + i) % a.length;
E e = a[p];
b.append(", ").append(e);
}
b.append("]");
return b.toString();
}
}
The most prominent error is that you do not instantiate the instance variables of Stack. Java uses default values for non-initialized values: primitive numbers are set to 0, booleans are set to false and all reference-types (i.e., Arrays and Objects) are set to null. This means that head and size are both initialized to 0 while a is initialized to null. The latter yields a NullPointerException when dereferencing its content.
Assuming you want to keep an array as your internal representation, you'd have to initialize an instance of E[] somehow. Unfortuantely, you cannot call new E[size]. See this other question on how to instantiate a generic array.
As for the initial value of head, which seems to be supposed to point to the top of the stack, you are not consistent in how you want to use it: In push, you use head as the index of the next free element in a and increment its value after adding the element. In toString, peek and pop, you use head as the index of the element that you want to return. Either representation is okay, but you must not mix them up.
Assuming you want head to always point to the last element, you would initialize it to -1 and increment its value in the push-method before accessing the index in a. Note the difference between head++ and ++head:
int i = head++;
is equivalent to
int i = head;
head = head + 1;
while
int i = ++head;
is equivalent to
head = head + 1;
int i = head;
so as a fix, you could change
return a[head++] = element;
to
return a[++head] = element;
but it is probably better to add a few lines of code and make the logic more explicit by incrementing the value of head first.
Now that we covered initialization, there's also a bug regarding the value of size: push should increment the size of the stack while pop should decrement it: However, in your code, size is never modified, hence empty is always true.
Also, I don't quite understand the idea behind the line
// Why DON'T we need to add a.length here like we did in push?
head = (head + 1) % a.length;
in pop. As an element is removed (and not added) I'd say this should simply be head = head - 1 or head-- if you prefer postfix-operators.
Putting it all together
Initialize the Stack properly, e.g.,
private E a[];
private int head = -1;
private int size = 0;
public Stack(Class<E> c, int maxSize){
#SuppressWarnings("unchecked")
final E[] a = (E[]) Array.newInstance(c, maxSize);
this.a = a;
}
Update the value of size in push and fix the update to head:
public E push(E element){
if (a.length == size){
throw new IllegalStateException("Cannot add to full stack");
}
size++;
return a[++head] = element;
}
Update the value of size and head in pop:
public E pop(){
if (empty()){
throw new java.util.EmptyStackException();
}
size--;
return a[head--];
}
Fixing toString
Remark: I kind of ignored the comments, as comments tend to lie as code gets refactored; but I just noticed that you wrote in a comment:
// Since the remainder of the stack is to the RIGHT of the stack,
// adding a new element pushes the head to the LEFT (+ wrap around)
which is actually the opposite of what the next line in your code tells: return a[head++] = element;. The proposed bugfixes are based on the code, not the comment, hence the remainder of the stack is to the LEFT of head. Because of that, the implementation of toString must be changed to print the array from right to left instead of left to right:
public String toString(){
if (empty())
return "[]";
StringBuilder b = new StringBuilder();
b.append("[").append(a[head]);
for (int i = head - 1; i >= 0; i--){
E e = a[i];
b.append(", ").append(e);
}
b.append("]");
return b.toString();
}
Is there an Iterator to loop over data structure in cycles?
Let's say there is an array:
int[] arr = {-1,5,7,-1,-1,-1}
I want to find index of first non -1 value from this array and starting to search from the random position (idx = random.nextInt(arr.length)). For example idx = 4;
So first check if arr[4] == -1, then if arr[5] == -1 and so on. If the end of the array reached then start from 0 position and continue until non -1 found. It is guaranteed that there will be at least one value not equal to -1 in the array.
This can be done so:
int idx = -1;
for (int i = random.nextInt(arr.length); ; i++) {
if (i == arr.length) {
/** start over */
i = 0;
}
if (-1 != arr[i]) {
idx = i;
break;
}
}
Or so:
int idx = -1;
int i = random.nextInt(arr.length);
do {
if (-1 != arr[i]) {
idx = i;
}
i == arr.length ? i=0 : i++;
} while (-1 == idx);
Is there an Iterator, that supports cycling (call next() , if the end of array reached then automatically start from 0)?
Limitations: 1) efficiency is not considered; 2) standard Java API is preferred.
in java API there is no such api which satisfy your problem but you can made it by your own.
what you can do is use List to create LinkedList. to solve your problem.
you can extend List to your class (CircularLinkedList extends List) & then override method hasNext() & getNext() thats all you need.
I don't think there are any iterators that let you know the index of the element as you call next(), so you'd have to keep track of the current index separately. You might be able to build up a "wrap-around" iterator using Guava's Iterators.concat (or some other third-party class) to concatenate an iterator over the trailing part of the array with an iterator over the leading part. However, I think the code is likely to be more complex than a simple for loop or two.
I believe there is no such circular Iterator that will automatically go to the beginning of the array once the end has been reached. I have created one below (not tested, and design is flawed), which requires an entirely new class of code, and is much longer than your short for/while loops.
public class MyCircularIterator<E> implements Iterator<E> {
private List<E> list;
private int pos;
public MyCircularIterator(List<E> list) {
this(list, 0);
}
public MyCircularIterator(List<E> list, int start) {
this.list = list;
pos = start;
}
public boolean hasNext() {
if(list.get(pos) != -1) return false;
return true;
}
public E next() {
if(hasNext()) {
E obj = list.get(pos);
pos = (pos + 1) % list.size();
return obj;
}
}
public void remove() {
list.remove(this.nextIndex);
}
}
I am using array based MinHeap in java. I am trying to create a custom method which can remove any element not only root from the heap but couldn't. Below is MinHeap code-
public class MinHeap {
/** Fixed-size array based heap representation */
private int[] h;
/** Number of nodes in the heap (h) */
private int n = 0;
/** Constructs a heap of specified size */
public MinHeap(final int size) {
h = new int[size];
}
/** Returns (without removing) the smallest (min) element from the heap. */
public int peek() {
if (isEmpty()) {
throw new RuntimeException("Heap is empty!");
}
return h[0];
}
/** Removes and returns the smallest (min) element from the heap. */
public int poll() {
if (isEmpty()) {
throw new RuntimeException("Heap is empty!");
}
final int min = h[0];
h[0] = h[n - 1];
if (--n > 0)
siftDown(0);
return min;
}
/** Checks if the heap is empty. */
public boolean isEmpty() {
return n == 0;
}
/** Adds a new element to the heap and sifts up/down accordingly. */
public void add(final int value) {
if (n == h.length) {
throw new RuntimeException("Heap is full!");
}
h[n] = value;
siftUp(n);
n++;
}
/**
* Sift up to make sure the heap property is not broken. This method is used
* when a new element is added to the heap and we need to make sure that it
* is at the right spot.
*/
private void siftUp(final int index) {
if (index > 0) {
final int parent = (index - 1) / 2;
if (h[parent] > h[index]) {
swap(parent, index);
siftUp(parent);
}
}
}
/**
* Sift down to make sure that the heap property is not broken This method
* is used when removing the min element, and we need to make sure that the
* replacing element is at the right spot.
*/
private void siftDown(int index) {
final int leftChild = 2 * index + 1;
final int rightChild = 2 * index + 2;
// Check if the children are outside the h bounds.
if (rightChild >= n && leftChild >= n)
return;
// Determine the smallest child out of the left and right children.
final int smallestChild = h[rightChild] > h[leftChild] ? leftChild
: rightChild;
if (h[index] > h[smallestChild]) {
swap(smallestChild, index);
siftDown(smallestChild);
}
}
/** Helper method for swapping h elements */
private void swap(int a, int b) {
int temp = h[a];
h[a] = h[b];
h[b] = temp;
}
/** Returns the size of heap. */
public int size() {
return n;
}
}
How can i design a method to remove any element from this MinHeap?
If you know the index of the element to be removed,
private void removeAt(int where) {
// This should never happen, you should ensure to call it only with valid indices
if (n == 0) throw new IllegalArgumentException("Trying to delete from empty heap");
if (where >= n) throw new IllegalArgumentException("Informative error message");
// Now for the working cases
if (where == n-1) {
// removing the final leaf, trivial
--n;
return;
}
// other nodes
// place last leaf into place where deletion occurs
h[where] = h[n-1];
// take note that we have now one element less
--n;
// the new node here can be smaller than the previous,
// so it might be smaller than the parent, therefore sift up
// if that is the case
if (where > 0 && h[where] > h[(where-1)/2]) {
siftUp(where);
} else if (where < n/2) {
// Now, if where has a child, the new value could be larger
// than that of the child, therefore sift down
siftDown(where);
}
}
The exposed function to remove a specified value (if present) would be
public void remove(int value) {
for(int i = 0; i < n; ++i) {
if (h[i] == value) {
removeAt(i);
// assumes that only one value should be removed,
// even if duplicates are in the heap, otherwise
// replace the break with --i to continue removing
break;
}
}
}
Summarising, we can remove a node at a given position by replacing the value with the value of the last leaf (in the cases where the removal is not trivial), and then sifting up or down from the deletion position. (Only one or none sift needs to be done, depending on a comparison with the parent and/or children, if present.)
That works because the heap invariant is satisfied for the parts of the tree above and below the deletion position, so if the new value placed there by the swap is smaller than the parent, sifting up will place it in its proper position above the deletion position. All elements moved are smaller than any element in the children, so the heap invariant is maintained for the part below (and including) the deletion position.
If the new value is larger than one of the direct children, it's basically a removal of the root from the sub-heap topped at the deletion position, so the siftDown restores the heap invariant.
The fix for the mentioned flaw in the siftDown method is to set smallestChild to leftChild if rightChild >= n:
final int smallestChild = (rightChild >= n || h[rightChild] > h[leftChild]) ? leftChild
: rightChild;