This is my code. There is an error showing on the terminal window. It says java.lang.ArrayIndexOutOfBoundsException: -1 at top--; and while (!stack.isEmpty()). Please help me solve this issue. I looked it up online but it did not help much. That is why I am asking you for help.
import java.util.*;
public class ArrayStack<T> implements StackADT<T>
{
private final static int DEFAULT_CAPACITY = 100;
private int top;
private T[] stack;
public ArrayStack()
{
this(DEFAULT_CAPACITY);
}
public ArrayStack(int initialCapacity)
{
top = 0;
stack = (T[])(new Object[initialCapacity]);
}
public void push(T element)
{
if (size() == stack.length)
expandCapacity();
stack[top] = element;
top++;
}
private void expandCapacity()
{
stack = Arrays.copyOf(stack, stack.length * 2);
}
public T pop() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException("stack");
top--;
T result = stack[top];
stack[top] = null;
return result;
}
public T peek() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException("stack");
return stack[top-1];
}
public boolean isEmpty()
{
return stack.length == 0;
}
public int size()
{
return top;
}
public static void main(String[] args)
{
ArrayStack<Character> stack = new ArrayStack<Character>();
String sentence = " ", word;
Scanner in = new Scanner(System.in);
System.out.println("Enter a sentence:");
sentence= in.nextLine();
System.out.println("Reversing each word:");
Scanner sentenceScanner = new Scanner(sentence);
while(sentenceScanner.hasNext())
{
word = sentenceScanner.next();
for(int i= 0; i<word.length(); i++)
{
stack.push(word.charAt(i));
}
while (!stack.isEmpty())
{
System.out.print(stack.pop());
}
}
}
}
Your isEmpty() and pop() functions do not work together. Think about this: when you decrement top and set the index to null does the actual size of the list get adjusted? The fix will come by changing isEmpty() I am just using pop() as an example.
Your isEmpty() method is implemented incorrectly.
public boolean isEmpty()
{
return stack.length == 0;
}
It is currently comparing the size or capacity of of the stack array. This is a constant, it does not change. The value of
stack.length
is always equal to the value you used to initialize the array
new Object[length];
You should be comparing to the number of elements in your stack.
public boolean isEmpty()
{
return top == 0;
}
Related
The task is to implement a generic stack (can not use the libraries from java), make the user input an expression using true and false for booleans b1 and b2, logical operators (and, or, not, iff, implies) recognize if its boolean or operator and send to 2 stacks, then poping the stacks to evaluate if its a valid expression, i.e: input:(b1 and b2) implies b3 is a valid expression but B3 and (b2 or) is not, I have issues with the stack part, since the peek is not returning any element, here is my code so far, note: the charat is because I would be checking that the brackets are balanced as well:
public class MyStack<T> {
class StackOverFlowException extends RuntimeException{}
class EmptyStackException extends RuntimeException{}
private T[] stack;
private int top;
public MyStack(int size) {
this.stack = (T[]) new Object[size];
this.top = 0;
}
public boolean isEmpty() {
return this.top == 0;
}
public boolean isFull() {
return this.top == stack.length;
}
public void push(T x) {
if(top == stack.length) {
throw new StackOverFlowException();
}
else {
this.stack[top] = x;
top++;
}
}
public T pop() {
if(isEmpty()) {
throw new EmptyStackException();
}
else {
T value = this.stack[--top];
return value;
}
}
public T peek() {
return this.stack[top];
}
public static void main(String[] args) {
MyStack<String> tf = new MyStack(100);
MyStack<String> operators = new MyStack(100);
System.out.println("Please input the expression to evaluate: ");
Scanner scn = new Scanner(System.in);
String expression = scn.nextLine();
String tokens[] = expression.split(" ");
int n = tokens.length;
boolean P1 = true;
boolean P2 = true;
boolean result = true;
for(int i = 0; i < n; i++ ) {
String separate = tokens[i];
char x = separate.charAt(i);
if(tokens[i].equalsIgnoreCase("true")||tokens[i].equalsIgnoreCase("false")) {
tf.push(separate);
tf.peek();
}
else if(tokens[i].equalsIgnoreCase("and")||tokens[i].equalsIgnoreCase("not")||tokens[i].equalsIgnoreCase("or")||tokens[i].equalsIgnoreCase("implies")||tokens[i].equalsIgnoreCase("iff")) {
operators.push(separate);
}
else {
System.out.println("Expression not Valid!");
}
}
}
The top variable is being misinterpreted in the peek() method (as well as the isEmpty() method).
As implemented, top is a misnomer since it is actually the size of the stack (which may also be considered the index for the next element to be pushed). So your peek() method should be looking at the element before top.
Alternatively, you may to define top as the element at the top of the stack, as this is generally how you are using it elsewhere. In this case, you will need to define a flag value to indicate the stack is empty.
In any case, you need handle the empty Stack case in the peek() method.
public class MyStack {
private static final int EMPTY = -1;
private int top = EMPTY;
... other stuff ...
public boolean isEmpty() {
return EMPTY == top;
}
public T peek() {
if (ifEmpty()) {
throw new EmptyStackException("Cannot peek into empty Stack");
}
return stack[top];
}
}
For this method I needed to implement a custom made Stack class to see if the given string is a palindrome.
This is the custom Stack class:
public class Stack<T> {
private ArrayList<T> arrayList = new ArrayList<>();
private T head;
public Stack() {
arrayList.add(head);
}
#Override
public String toString() {
return arrayList.toString();
}
public boolean empty() {
return arrayList.size() == 1 ? true : false;
}
public T push(T element) {
arrayList.add(element);
head = element;
return element;
}
public T pop() {
T returnVal = arrayList.get(arrayList.size()-1);
if (!empty()) {
arrayList.remove(returnVal);
head = arrayList.get(arrayList.size()-1);
}
return returnVal;
}
public T peek() {
return head;
}
}
And this is the palindrome method:
public static boolean isPalindrome(String string) {
var stack = new Stack<Character>();
var flag = true;
for (int i=0; i<string.length(); i++)
stack.push(string.charAt(i));
if (string.charAt(0) == stack.peek()) {
for (int j=0; j<string.length(); j++) {
System.out.println(string.charAt(j) + " " + stack.peek());
if (string.charAt(j) != stack.pop()) {
flag = false;
break;
}
}
}
else
return false;
return flag;
}
When I run the method, it runs the loop only 2 times. The Stack object doesn't seem to pop. But when I tested the pop() method in the main method with just a set of different characters, it seemed to work. But in this isPalindrome() method, it doesn't seem to me that it works. Can someone please help out?
In your Stack.pop() method, the line arrayList.remove(returnVal); is not what you want.
It will remove the first occurrence of returnVal from the stack, but in pop() you need to remove the last occurrence of returnVal.
In Stack.pop() you need to remove the last element - which means you need to write
arrayList.remove(arrayList.size()-1);
Your complete Stack.pop() method would then be:
public T pop() {
T returnVal = arrayList.get(arrayList.size()-1);
if (!empty()) {
arrayList.remove(arrayList.size()-1);
head = arrayList.get(arrayList.size()-1);
}
return returnVal;
}
I am trying to print the elements of stack S in reverse (using a "for" loop), but so far I haven't had any success.
I have managed to do it with "pop" fairly easily, but the second way evades me. My solution for "pop" is commented out at the end of the code.
Any help will be appreciated.
PS. Most of this code is irrelevant to the question, but if I knew what and where I can cut out, I probably wouldn't need help at all. Sorry.
package simplearraystackofchars;
public class SimpleArrayStackofchars implements Stack {
protected int capacity; // The actual capacity of the stack array
public static final int CAPACITY = 2; // default array capacity
protected Object S[], K[]; // Generic array used to implement the stack
protected int top = -1; // index for the top of the stack (-1 = empty stack)
public SimpleArrayStackofchars() {
this(CAPACITY); // default capacity
}
public SimpleArrayStackofchars(int cap) {
capacity = cap;
S = new Object[capacity];
}
public int size() {
return (top + 1);
}
public boolean isEmpty() {
return (top == -1);
}
public void push(Object element) throws FullStackException {
if (size() == capacity) {
//throw new FullStackException("Stack is full. Stack size max is "+ capacity);
// can replace previous line with code to double stack size
doubleArray();
}
S[++top] = element;
}
public Object top() throws EmptyStackException {
if (isEmpty()) {
throw new EmptyStackException("Stack is empty.");
}
return S[top];
}
public Object pop() throws EmptyStackException {
Object element;
if (isEmpty()) {
throw new EmptyStackException("Stack is empty.");
}
element = S[top];
S[top--] = null; // dereference S[top] for garbage collection.
return element;
}
private void doubleArray() {
Object[] newArray;
System.out.println("Stack is full (max size was " + capacity + "). Increasing to " + (2 * capacity));
//double variable capacity
capacity = 2 * capacity;
newArray = new Object[capacity];
for (int i = 0; i < S.length; i++) {
newArray[i] = S[i];
}
S = newArray;
}
public static void main(String[] args) {
Stack S = new SimpleArrayStackofchars();
S.push("1");
S.push("2");
S.push("3");
S.push("4");
S.push("5");
S.push("6");
// Stack K is created by popping elements of Stack S from the top.
// This reverses the order.
//
// Stack K = new SimpleArrayStackofchars();
// while (!S.isEmpty()) {
// K.push(S.pop());
// }
// while (!K.isEmpty()) {
// System.out.println(K.pop());
// }
while (!S.isEmpty()) {
System.out.println(S.pop());
}
}
}
Not really sure about what you need that for loop for, but this should produce the same result:
Stack K = new SimpleArrayStackofchars();
for (int i = 0, i < S.size(); i++) {
K.push(S.pop());
}
for (int i = 0, i < K.size(); i++) {
System.out.println(K.pop());
}
I was working on my code and I'm stuck at this point.
My question is to evaluate postfix notation entered from the keyboard.
Here is my code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.NoSuchElementException;
interface Stack<E> {
// The elements of the Stack are any kind of objects
// Access methods:
public boolean isEmpty ();
// Returns true only if the stack is empty.
public E peek ();
// Returns the element on the top od the stack.
// Transformation methods:
public void clear ();
// Clears the stack.
public void push (E x);
// Adds x on the top of the stack.
public E pop ();
// Removes and returns the element on the top.
}
class ArrayStack<E> implements Stack<E> {
private E[] elems;
private int depth;
#SuppressWarnings("unchecked")
public ArrayStack (int maxDepth) {
// Creating new empty stack
elems = (E[]) new Object[maxDepth];
depth = 0;
}
public boolean isEmpty () {
// Returns true only if the stack is empty.
return (depth == 0);
}
public E peek () {
// Returns the element on the top od the stack.
if (depth == 0)
throw new NoSuchElementException();
return elems[depth-1];
}
public void clear () {
// Clears the stack.
for (int i = 0; i < depth; i++) elems[i] = null;
depth = 0;
}
public void push (E x) {
// Adds x on the top of the stack.
elems[depth++] = x;
}
public E pop () {
// Removes and returns the element on the top.
if (depth == 0)
throw new NoSuchElementException();
E topmost = elems[--depth];
elems[depth] = null;
return topmost;
}
}
public class PostFixEvaluation {
static int evaluatePostfix(char [] izraz, int n)
{
ArrayStack e;
char ch;
int op1,op2,result=0;
int i=0;
while(i<n)
{
if(Character.isDigit(izraz[i]))
{
ch=izraz[i];
e.push(ch);
}
else
{
ch=izraz[i];
op1 =(int)e.pop();
op2 =(int)e.pop();
if(ch=='+')
{
result=op1+op2;
}
if(ch=='-')
{
result=op1-op2;
}
if(ch=='/')
{
result=op1/op2;
}
if(ch=='*')
{
result=op1*op2;
}
e.push(result);
}
i++;
}
return result;
}
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String expression = br.readLine();
char exp[] = expression.toCharArray();
int rez = evaluatePostfix(exp, exp.length);
System.out.println(rez);
br.close();
}
}
My problem is at the evaluatePostfix function. I can't use the push and pop functions because it gives me this error:
PostFixEvaluation.java:100: error: variable e might not have been initialized
e.push(ch);
^
PostFixEvaluation.java:105: error: variable e might not have been initialized
op1 =(int)e.pop();
^
Note: PostFixEvaluation.java uses unchecked or unsafe operations.
Can anyone help me solve this problem?
static int evaluatePostfix(char [] izraz, int n)
{
ArrayStack e;
char ch;
int op1,op2,result=0;
int i=0;
while(i<n)
{
if(Character.isDigit(izraz[i]))
{
ch=izraz[i];
e.push(ch);
}
else
{
ch=izraz[i];
op1 =(int)e.pop();
op2 =(int)e.pop();
if(ch=='+')
{
result=op1+op2;
}
if(ch=='-')
{
result=op1-op2;
}
if(ch=='/')
{
result=op1/op2;
}
if(ch=='*')
{
result=op1*op2;
}
e.push(result);
}
i++;
}
return result;
}
Initialize e in function evaluatePostfix
ArrayStack<Character> e = new ArrayStack(10); // maxDepth = 10
I need to modify a class to create a dynamic array stack.
My code at this point looks something like this:
public class DynamicArrayStack<E> implements Stack<E> {
private E[] elems; //used to store the elements
public static final int defaultIncrement = 25;
private final int increment;
private int top;
#SuppressWarnings( "unchecked" )
public DynamicArrayStack( int increment ) {
this.increment = increment;
elems = (E[]) new Object[ increment ];
top = 0;
}
/**
* Constructor with no parameter that will initialize
* the stack to have an array whose size is the value
* of increment and memorise that value as the value
* of increment.
*/
public void ArraySize() { }
public boolean isEmpty() {
return top == 0;
}
public E peek() {
return elems[ top-1 ];
}
public E pop() {
// save the top element
E saved = elems[ --top ];
// scrub the memory, then decrements top
elems[ top ] = null;
return saved;
}
public void push( E elem ) {
// stores the element at position top, then increments top
elems[ top++ ] = elem;
}
public String toString() {
StringBuffer b;
b = new StringBuffer( "DynamicArrayStack: {" );
for ( int i=top-1; i>=0; i-- ) {
if ( i!=top-1 ) {
b.append( "," );
}
b.append( elems[ i ] );
}
b.append( "}" );
return b.toString();
}
}
How do I edit the first constructor to set increment as the initial size of the stack and that same value to be used when increasing or decreasing the size of the array. My method for doing this seems way too simple. Parameter must be > 0 and a fixed number of cells are added or removed when the size of the array changes.
The second constructor should set the stack to have an array whose size is the value of increment. I keep getting errors here because I can't figure out how to do that because I thought that was already set in the first constructor. Also the size of the array as the value of increment.
Also how do I make this class capable of changing the capacity of the stack and into which method should I place that code?
Here is the simple java code to implement it:
1)Stack based:
public class DynamicArrayStack {
public static void main(String[] args) {
DynamicStack dstack=new DynamicStack(2);
System.out.println("--Pushing--");
dstack.push(1);
dstack.push(2);
dstack.display();
dstack.push(3);
dstack.push(2);
dstack.push(5);
dstack.display();
System.out.println("--Popping--");
dstack.pop();
dstack.pop();
dstack.pop();
dstack.display();
}
}
class DynamicStack {
private int top;
private int capacity;
private int[] array;
public DynamicStack(int cap) {
capacity = cap;
array = new int[capacity];
top = -1;
}
public void push(int data) {
if (isFull()){
expandArray(); //if array is full then increase its capacity
}
array[++top] = data; //insert the data
}
public void expandArray() {
int curr_size = top + 1;
int[] new_array = new int[curr_size * 2];
for(int i=0;i<curr_size;i++){
new_array[i] = array[i];
}
array = new_array; //refer to the new array
capacity = new_array.length;
}
public boolean isFull() {
if (capacity == top+1)
return true;
else
return false;
}
public int pop() {
if (isEmpty()) {
System.out.println("Stack is empty");
return -1;
} else {
reduceSize(); //function to check if size can be reduced
return array[top--];
}
}
public void reduceSize() {
int curr_length = top+1;
if (curr_length < capacity / 2) {
int[] new_array = new int[capacity / 2];
System.arraycopy(array, 0, new_array, 0, new_array.length);
array = new_array;
capacity = new_array.length;
}
}
public boolean isEmpty() {
if (top == -1)
return true;
else
return false;
}
public void display() {
for (int i = 0; i <= top; i++) {
System.out.print(array[i] + "=>");
}
System.out.println();
System.out.println("ARRAY SIZE:" + array.length);
}
}
OUTPUT:
--Pushing--
1=>2=>
ARRAY SIZE:2
1=>2=>3=>2=>5=>
ARRAY SIZE:8
--Popping--
1=>2=>
ARRAY SIZE:4
2)Link List based:
public class LinkListStack {
public static void main(String[] args) {
StackList stack = new StackList();
System.out.println("--Pushing--");
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
stack.push(6);
stack.display();
System.out.println("--Popping--");
stack.pop();
stack.pop();
stack.display();
}
}
class Node {
private int data;
private Node next;
public Node(int d) {
data = d;
next = null;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
class StackList {
private Node top;
private int length;
public StackList() {
length = 0;
top = null;
}
public void push(int data) {
Node temp = new Node(data);
if (top == null) {
top = temp;
} else {
temp.setNext(top);
top = temp;
}
length++;
}
public int pop() {
Node temp=top;
int data = top.getData();
top = top.getNext();
temp=null;
length--;
return data;
}
public void display() {
Node temp = top;
if (isEmpty()) {
System.out.println("Stack is empty");
} else {
while (temp != null) {
System.out.print(temp.getData() + "=>");
temp = temp.getNext();
}
}
System.out.println();
}
public boolean isEmpty() {
return (top == null);
}
}
OUTPUT:
--Pushing--
6=>5=>4=>3=>2=>1=>
--Popping--
4=>3=>2=>1=>
Default constructor
Your default constructor could simply call your other constructor with a default increment value. For example:
public DynamicArrayStack() {
this(defaultIncrement);
}
Expanding the array
The correct place to expand the array is within the push method. When attempting to add a new element you can check if the array is large enough, and if not create a new larger array. For example you could do the following:
#Override
public E push(final E elem) {
// Check if we need to expand the array
if (elems.length - 1 == top) {
#SuppressWarnings("unchecked")
final E[] newElems = (E[]) new Object[elems.length + increment];
System.arraycopy(elems, 0, newElems, 0, elems.length);
elems = newElems;
}
// stores the element at position top, then increments top
elems[top++] = elem;
return elem;
}
If you want to shrink the array the sensible place to do this would be in the pop() method. You might want to consider only reducing the length when (top + (increment*2))<elems.length to avoid repeatedly copying arrays when you're on the boundary.