java stack reading from an array throws ArrayIndexOutOfBoundsException - java

I need to fill a stack from an array, then print out the elements in order and then again reversing the order. What I'm having problems with is I'm getting an ArrayIndexOutOfBoundsException and cant figure out where it is coming from. I have tried running through the debug and it appears as I'm popping off elements it never reaches the last element. Below is my code:
public class arrayStack {
private int top;
private String[] storage;
public arrayStack(int capacity)
{
storage = new String[capacity];
top = -1;
}
public boolean isEmpty() {
return (top == 0);
}
String peek() {
return storage[top];
}
String pop() {
top--;
return storage[top];
}
public void push(String str) {
top++;
storage[top] = str;
}
}
StackMain.java:
public class StackMain {
public static void main(String[] args) {
//int j = 5;
String[] list = new String[5];
list[0] = "Beware";
list[1] = "The";
list[2] = "Ides";
list[3] = "Of";
list[4] = "March";
arrayStack stack = new arrayStack(5);
for(int i = 0; i < list.length; i++)
{
stack.push(list[i]);
}
for(int j = 0; j < list.length; j++)
System.out.println(stack.pop());
}
}

In pop(), you need to return the item that was popped, which is the item at the index of the old value of top. Cleanest way is to change the function to
String pop() {
return storage[top--];
}
Edit
You also need to change isEmpty() to return (top == -1). You could also change the implementation to use size (the number of elements) instead of top (the index of the highest element) like others mentioned.

In your constructor for arrayStack, you should set top to 0, rather than to -1. In your isEmpty method, you even check that top == 0, so clearly top == 0 means empty, rather than top == -1. This is why you always miss the last element when popping off values from the stack; putting the first element increments top to 0.
Oh, and I missed what tom said, below: decrementing top before you find the value at the top will return the wrong element. His code below is preferable, but this might be more easy to understand for a beginner:
public String pop() {
String topValue = storage[top];
top--;
return topValue;
}

If you push(String) just one element, with top initialized to -1, what will the value of top be after the push?
Now look at your pop() function, it decrements top before trying to get the element requested, so what array index is it going to try to access if you've pushed just one element?

Since you start top at -1, once you have added your 5 elements from the String array top will be 4, which is incorrect since you have 5 elements.
Then when you try to pop the stack 5 times, top goes back to -1 and storage[-1] doesn't exist so you get an ArrayIndexOutOfBoundsException
Start top at 0.
Alternatively if you decrement top after you retrieve the element from you stack, you won't get an error; but it would be better to start top at 0 because top is really representing the number of elements in your stack.

Please tag the question as homework. And coming to the problem, the problem is in the pop() function. You are decrementing the value of top first and then returning the element. But when you check the push() function, you are incrementing first and then adding the element. So, if you move the top-- to after getting the element from the stack your problem will be solved.

Your pop method is incorrect. In your code here, top starts at negative 1.
When you push an element, top becomes 0.
When you pop an element, the top becomes -1 before you access the element.
Also, your empty method is incorrect. In the initial state of the stack, top = -1, and isEmpty checks if it returns 0. Initially the stack should be empty.

your pop() function must be changed. You must store storage[pop] in a temporary variable and then reduce top by 1 and then return the temporary variable

It would be great if you can include java 1.5 generics facility to implement stack.Then your stack will be more flexible.It can hold any type of objects(in you case only Strings)
And one more advice is in the pop method you should tell garbage collector to discard to poped object as follows. (In the case if you are using generics) Following is a more flexible stack implementation which mentioned in effective java edition 2.
// Initial attempt to generify Stack = won’t compile!
public class Stack<E> {
private E[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = (E[])new E[DEFAULT_INITIAL_CAPACITY];
}
public void push(E e) {
ensureCapacity();
elements[size++] = e;
}
public E pop() {
if (size==0)
throw new EmptyStackException();
E result = elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}

Related

Is this the right way to use method "add"?

So my friend created a queue class which has an instance variable size = 0; and for the add method he uses.
But what will happen to index 0 in this case?
It will not have an elements declared to it since add starts from size++. Which is 1 starting position.
public void add(T data) {
if(size > elements.length) {
throw new QueueException("Queue is full");
}
elements[size++] = data;
}
size++ returns the size value before it gets incremented in the background. Because of that the elements[0] will be assigned. See Oracle Tutorial on incrementing.
The problem is with the last element. The code will attempt to assign elements[elements.length] which is above the array capacity. The guard should be:
if (size >= elements.length) {
throw new QueueException("Queue is full");
}

JAVA Queue Implementation using Arrays

I'm trying to implement Queues in JAVA. I'm a beginner. I dont understand why this isn't working. Push() works fine but pop() isn't working. Can someone please point out where im going wrong?
pop():
public void pop()
{
for(int i=0;i<length;i++)
{
while(i<(length-1))
{
arr[i]=arr[i+1];
}
}
}
push():
public void push(int x)
{
push:for(int i=0;i<length;i++)
{
if(arr[i]==null)
{
arr[i]=x;
break push;
}
}
}
show():
public void show()
{
int c=0;
for(int i=0;i<length;i++)
//if(arr[i]!=null)
{
System.out.println(arr[i]);
c++;
}
System.out.println("Current Capacity "+c+"/"+length);
}
main()
public static void main(String...i)
{
System.out.println("Stack Implementation");
Queue stack = new Queue();
System.out.println("Push");
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
stack.show();
System.out.println("Pop");
stack.pop();
stack.show();
}
The output doesn't show any data after pop() is run.
You don't increment i in pop() so the while loop will run endlessly.
In push you are using a for loop which increments i: :for(int i=0;i<length;i++ /*here*/)
You also don't initialize i in pop() so it will probably have the value of the last increment in push(). That value will be the index of the next empty element (if there's one left) and thus that's wrong anyways. However, you want to pop from the front, so you'd need to start at i = 0 - in that case another for loop would work as well, i.e. you just copy the value of element at i+1 to the index i and set the last element to null (for more efficiency you could stop once i+1 has a null element).
Edit: now that you've posted more code for pop() the situation is a little different. You are already using a for loop in pop() but another loop inside that. I assume you want to do if(i<(length-1)) instead of while(i<(length-1)) - but in that case you'd still have to handle the last element, i.e. once the queue was full you'd need to set the last element to null when you pop one and move the rest.
When you pushed the element you need to return from the method:
public void push(int x) {
for (int i = 0; i < length; i++) {
if (arr[i] == null) {
arr[i] = x;
return; // Exit from push when you added the element in the right position
}
}
}
Note that this code is not optimized. Push an element requires O(n), so can waste a lot of time for big queues, but this is the closest solution to your code. Anyway a simple optimization can be done introducing a variable holding the last used index. So you can use that variable to push and pop an element in O(1).

Computing the size of a linked list using recursion/helper function - Java

Beginner here using Java (first year student), and am unable to get the below function to work. The goal is to use recursion and a helper function to compute the size of a singly linked list. When running the code against test lists, it keeps returning List changed to [].
I'm struggling in general with Java, so any help is appreciated. Thank you
public class MyLinked {
static class Node {
public Node(double item, Node next) {
this.item = item;
this.next = next;
}
public double item;
public Node next;
}
int N;
Node first;
public int sizeForward() {
return sizeForwardHelper(first);
}
public int sizeForwardHelper(Node n) {
Node current = first;
if (current == null) {
return 0;
} else {
first = first.next;
return sizeForward() + 1;
}
}
I believe I have the first portion set up to return 0 if there are no elements in the List. I believe it's the second part that isn't setting up correctly?
Thanks
Because it’s important for your learning to not spoonfeed you, I’ll describe an approach rather than provide code.
Use this fact:
The length of the list from any given node to the end is 1 plus the length measured from the next node (if there is one).
Usually (as would work here), recursive functions take this form:
If the terminating condition is true, return some value
Otherwise, return some value plus the recursively calculated value
When writing a recursive function, first decide on the terminating condition. In this case, n == null is the obvious choice, and you’d return 0, because you’ve run off the end of the list and the length of nothing (ie no node) is nothing. This also handles the empty list (when first is null) without any special code.
Otherwise, return 1 (the length of one node) plus the length of next.
Put that all together and you’ll have your answer.
——
Hint: The body of the recursive helper method can be coded using one short line if you use a ternary expression.
Instead of calling your wrapper function call your helper function recursively. Try the following:
public int sizeForward () {
return sizeForwardHelper (first);
}
public int sizeForwardHelper(Node n) {
if (n == null) // base case
return 0;
return sizeForwardHelper(n.next) + 1; // count this node + rest of list
}
Your method that computes the size of the list actually modifies the list in the process (with first = first.next; you set the first element to the next, and since there is a recursion, the first element always end up being null which is equivalent to an empty list with your design). Your method will work once, but your list will be empty afterwards.
To illustrate this, I added a print next to the instruction first = first.next; and wrote the following main:
public static void main(String[] args) {
Node n2 = new Node(2d, null);
Node n1 = new Node(1d, n2);
Node n = new Node(0, n1);
MyLinked l = new MyLinked(n);
System.out.println("The first element is: "+l.first.item);
System.out.println("The size is: "+l.sizeForward());
System.out.println("The first element is: "+l.first);
}
It yields:
The first element is: 0.0
first is set to 1.0
first is set to 2.0
first is set to null
The size is: 3
The first element is: null
Clearly, you should not modify the list while computing its size. The helper method should return 0 if the node is null (empty list), and 1 plus the size of the rest of the list otherwise. Here is the code.
public int sizeForwardHelper(Node n) {
if (n == null)
return 0;
else
return sizeForwardHelper(n.next) +1;
}
The goal of the arg free method sizeForward() is just to call the helper. The helper should not use it though.

Iterator stack hasNext() not returning true

I'm trying to iterate over an Object array. Using the next() method works so I'm guessing that my iterator class and constructors are working.
For some reason i'm not getting any output while the hasNext() method is running.
Iterator it = hej.iterator();
Object j = it.next();
System.out.println(j);
while(it.hasNext()){
Object i = it.next();
System.out.println(i + " ");
}
With "hej" being my Object array.
My code for the next(); and hasNext() methods are as follows:
public class StackIterator implements Iterator<Object>{
// fields
private int element = 0;
private final Object[] elements;
private final int max;
// constructor
public StackIterator(Object[] values, int maxIndex) {
elements = values;
max = maxIndex;
}
// methods
public boolean hasNext() {
return element < max;
}
public Object next() {
return elements[element++];
}
}
The file that constructs the Object Array and the Object Array depends on an interface:
public interface Stack {
int size();
boolean isEmpty();
void push(Object element);
Object pop();
Object peek();
Iterator<Object> iterator();
}
The methods are then explained in another file:
public class StackExample implements Stack {
// fields
int length = 0;
Object[] arr;
// constructor
public StackExample() {arr = new Object[length];}
// method returns size of object array
public int size() {
return arr.length;
}
// method checks if object is empty
public boolean isEmpty() {
boolean result = false;
if (arr.length == 0){
result = true;
}
return result;
}
// method for push
public void push(Object element) {
newBiggerObj();
arr[0] = element;
}
// returns the first object of the stack
public Object pop() {
Object[] temp = new Object[arr.length-1];
Object first = arr[0];
for (int i = 0; i<arr.length-1; i++){
temp[i] = arr[i+1];
}arr = temp;
return first;
}
// returns the object on top of stack
public Object peek() {
if (isEmpty()){
try{
throw new Exception("Stack empty, can't peek!");
}
catch(Exception e){
return e.getMessage();
}
}
else {
Object first = arr[0];
return first;
}
}
// method for push method
private void newBiggerObj(){
Object[] temp = new Object[arr.length+1];
for (int i = 0; i<arr.length; i++){
temp[i+1] = arr[i];
}
arr = temp;
}
public String toString(){
String str = "";
for (int i = 0; i < arr.length; i++){
str = str + arr[i] + " , ";
}return str;
}
public Iterator<Object> iterator() {
return new StackIterator(arr, length);
}
}
What bothers me is that the method Iterator is within itself returning an instance of the class Stack Iterator. Which i posted above. So my real problem seems to be that my fields are not being given any value, since I am not myself giving the any values within the constructor.
My main method in which I'm testing all of this is as follows:
public class Teststack {
public static void main(String[] args){
// new instane of class StackExample
StackExample hej = new StackExample();
// test for the different methods
System.out.println(hej.isEmpty());
System.out.println(hej.size());
hej.push(4);
hej.push("hej");
hej.push(6);
hej.push(5);
System.out.println(hej.size());
System.out.println(hej.peek());
System.out.println(hej.pop());
System.out.println(hej.toString());
System.out.println(hej.isEmpty());
System.out.println("Testing Iterator: ");
// test for iterator
Iterator it = hej.iterator();
Object j = it.next();
System.out.println(j);
while(it.hasNext()){
Object i = it.next();
System.out.println(i + " ");
}
}
}
In your StackExample class, I don't see the length variable being updated when elements are pushed or popped. Due to this, length will always be 0 and calls to it.hasNext() will always return false.
You don't need to pass the length as a separate argument. You can find the array's length in the StackIterator constructor and use it.
Also note that since you're creating a new array on every push and pop, the iterator returned by StackExample#iterator() will become stale after every push/pop since it will work on an old copy/state of the stack.
The problem is here:
public Iterator<Object> iterator() {
return new StackIterator(arr, length);
}
length field is never changed, so its value is always 0. You can change the code to this:
public Iterator<Object> iterator() {
return new StackIterator(arr, arr.length);
}
Also, before retrieving elements from the iterator, you should always call it.hasNext. The fact you did this:
Iterator it = hej.iterator();
Object j = it.next();
And worked was just pure luck.
Apart of this, I can sense you have a bad design on your stack implementation. Here are some hints to improve your code:
The inner array should be initialized with a default size different than 0. E.g. 10 (as done in java.util.ArrayList implementation).
You should avoid creating a new array when adding (push) or removing (pop) an element from your stack. Instead of this, you should use the length field to control how many elements are in your stack.
The value of the new size should be based on another formula rather than array.length + 1. For example, try using something like int newSize = array.length / 2 * 3;.
Resize the inner array only when necessary. When calling push, do it only if you precisely need to increase the size of the array. When calling pop, do it if the current length of the array (this is, array.length) is far greater than the value of length field of your class.
Never forget to update the value of length on push and pop methods.
Couple of issues:
You are calling Object j = it.next(); after creating iterator and then check for hasNext. You are incrementing the element index. Hence if you just have one element, you wont enter the while loop. In addition, if your custom datastructure is empty i.e. array has no elements then you are prone to ArrayIndexOutOfBoundException.
You will always iterate and print n-1 elements instead to n elements.
Once you iterated, then your pointer will always point to last element and never get resetted. So very next time you wont be able to iterate over your elements. Its a one time iterator.
Try not to call
Object j = it.next() statement, but just while cycle. Seems you have an array of just 1 element.
There are a number of problems with this code:
In the StackIterator constructor there is no bounds checking on maxIndex. Callers can pass in a number greater than values.length, less that 0, etc.
In the next method, there is no check of the end condition, either directly or by calling hasNext(). Callers can keep calling next() and see elements beyond max or even get an ArrayIndexOutOfBoundsException, when they should be getting a NoSuchElementException.
The Stack class never increments or decrements its length field when elements are pushed or popped.
The Stack class tracks the length separately from the array, even though it always resizes the array on every push or pop, but Java arrays already know their size. (But see the next item.)
The Stack class resizes the array on every push or pop, which is very inefficient. Typically classes like this only resize the array when necessary, allowing 'slack' space, to give amortized constant time performance (see ArrayList). If you do this, however, it is necessary to null out popped items to avoid unintentional object retention.
The Stack adds and removes elements at the beginning of the array. This is incredibly inefficient since it means a O(n) reshuffling must be done on every push or pop.
The peek() method takes into account the possibility that the Stack may be empty, but the pop() method does not. A pop() on an empty Stack will throw an ArrayIndexOutOfBoundsException.
Stack is not a generic class. It holds Object. Users of the Stack will have to cast the return values from peek() or pop(), and it isn't type safe. In your example, you show a stack that is a heterogeneous mixture of String and Integer. This is a very Java 1.2 way of doing things, and while it isn't necessarily wrong, you should consider parameterizing Stack.

Recursively finding indexes of an INT in an ever-shrinking LispList

2nd-year Computer-Science student here, and as part of a set of exercises on recursion, we've been given some arbitrary problems to solve with LispLists. I'm stuck half-way through, so if anyone can point me in the right direction without explicitly giving me the answer, that would be great.
I need to find the positions of every instance of intToFind in the LispList listToCheck - the only conditions are that:
no additional arguments can be used
it has to be done recursively
For everyone who hasn't encountered LispLists - they don't have indexing, and the only methods you can call on them are:
.isEmpty() returns boolean
.head() returns the element at the 0th position
.tail() returns a LispList of all elements that aren't the head
.cons(value) adds value to the 'head' position - shifting everything else one down
There's also one method I wrote previously called:
recursiveCountLength(list) returns an int of the length of the passed LispList.
The list I've been testing on is: [2,3,4,2,5,12,2,5], so the result I'm looking for is [0,3,6] - with that out the way, here's what I've got so far (explanation of what I'm attempting after):
public static LispList<Integer>
recursivePositions(LispList<Integer> listToCheck, int intToFind)
{
if(listToCheck.isEmpty()) return listToCheck;
else {
// go through the array in its entirety once through,
// do everything else 'on the way back up'
LispList<Integer> positions = recursivePositions(listToCheck.tail(), intToFind);
//get the current length and current head
int currentInt = listToCheck.head();
int currentLength = recursiveCountLength(listToCheck);
//if a match is found, add the current length of the list to the list
if(currentInt == intToFind) return positions.cons(currentLength);
else return positions;
}
}
My current theory is that length of the array at each encounter of the int we're looking for (in this case 2) subtracted from the original length of the list (in this case 8) will give us the indexes.
2 first happens with a length of 8 (8-8 = index of 0, so indexes now [0]),
2 next happens with a length of 5 (8-5 = index of 3, so indexes now [0, 3]),
2 lastly happens at a length of 2 (8-2 = index of 6, so indexes now [0, 3, 6]).
The only problem is that I can't figure out how to get a static '8' - which leaves me to conclude that I'm approaching this in entirely the wrong way. Does anyone have any tips for me here? Any help would be hugely appreciated.
To clarify: a LispList is just a singly-linked-list (to differentiate from a Java LinkedList, which is double-linked).
Usually, you'd use a helper that carries information into the recursive calls, such as the current position and the positions already found (the current partial result).
LispList<Integer> positions (final int item, final LispList<Integer> list) {
return positionsAux( item, list, 0, new LispList<Integer>() );
}
private LispList<Integer> positionsAux (final int item,
final LispList<Integer> list,
final int position,
final LispList<Integer> result) {
if (list.isEmpty()) {
return result.reverse();
}
if (list.head().intValue() == item) {
result = result.cons(position);
}
return positionsAux( item, list.tail(), position + 1, result );
}
If that is not allowed, you need to carry the results backwards. If you assume that the recursive call has returned the correct result for your list.tail(), you need to add 1 to each found position to get the right result for your list. Then, you cons a 0 to the result if the current element matches. This version is less efficient than the first, because you traverse the current result list for every element of the input list (so it is O(n·m) instead of O(n), where n is the length of the input list and m the length of the result list).
LispList<Integer> positions (final int item, final LispList<Integer> list) {
if (list.isEmpty()) {
return new LispList<Integer>();
}
final LispList<Integer> tailResult = positions( item, list.tail() );
final LispList<Integer> result = tailResult.addToEach( 1 );
if (list.head().intValue() == item) {
return result.cons( 0 );
} else {
return result;
}
}
Implementing reverse() for the first version and addToEach(int) for the second is left as an exercise to the reader.
You need at least 3 arguments. Pretty sure adding more arguments is okay since he allows helper methods (because otherwise you could just make your method call the helper method which has more arguments).
Simplest way recursively:
public static LispList<Integer> positions(LispList<Integer> list, Integer key, Integer position){
if (list.isEmpty()) return LispList.empty();
if (list.head().equals(key)) return positions(list.tail(), key, position+1).cons(position);
return positions(list.tail(), key, position+1);
}

Categories