From 1e507068cd3d397065b3721bea14447a33052704 Mon Sep 17 00:00:00 2001 From: Hardik Pawar <97388607+Hardvan@users.noreply.github.com> Date: Sat, 26 Oct 2024 13:08:32 +0530 Subject: [PATCH] Enhance docs, remove `main`, add tests in `StackArray` (#6019) --- .../datastructures/stacks/StackArray.java | 83 ++++++++++++++++++- .../datastructures/stacks/StackArrayTest.java | 66 ++++++++------- 2 files changed, 117 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/thealgorithms/datastructures/stacks/StackArray.java b/src/main/java/com/thealgorithms/datastructures/stacks/StackArray.java index f98db7cc1..9369b3fc9 100644 --- a/src/main/java/com/thealgorithms/datastructures/stacks/StackArray.java +++ b/src/main/java/com/thealgorithms/datastructures/stacks/StackArray.java @@ -1,7 +1,13 @@ package com.thealgorithms.datastructures.stacks; /** - * This class implements a Stack using a regular array. + * Implements a generic stack using an array. + * + *

This stack automatically resizes when necessary, growing to accommodate additional elements and + * shrinking to conserve memory when its size significantly decreases. + * + *

Elements are pushed and popped in LIFO (last-in, first-out) order, where the last element added + * is the first to be removed. * * @param the type of elements in this stack */ @@ -13,11 +19,20 @@ public class StackArray implements Stack { private T[] stackArray; private int top; + /** + * Creates a stack with a default capacity. + */ @SuppressWarnings("unchecked") public StackArray() { this(DEFAULT_CAPACITY); } + /** + * Creates a stack with a specified initial capacity. + * + * @param size the initial capacity of the stack, must be greater than 0 + * @throws IllegalArgumentException if size is less than or equal to 0 + */ @SuppressWarnings("unchecked") public StackArray(int size) { if (size <= 0) { @@ -28,6 +43,11 @@ public class StackArray implements Stack { this.top = -1; } + /** + * Pushes an element onto the top of the stack. Resizes the stack if it is full. + * + * @param value the element to push + */ @Override public void push(T value) { if (isFull()) { @@ -36,6 +56,13 @@ public class StackArray implements Stack { stackArray[++top] = value; } + /** + * Removes and returns the element from the top of the stack. Shrinks the stack if + * its size is below a quarter of its capacity, but not below the default capacity. + * + * @return the element removed from the top of the stack + * @throws IllegalStateException if the stack is empty + */ @Override public T pop() { if (isEmpty()) { @@ -48,6 +75,12 @@ public class StackArray implements Stack { return value; } + /** + * Returns the element at the top of the stack without removing it. + * + * @return the top element of the stack + * @throws IllegalStateException if the stack is empty + */ @Override public T peek() { if (isEmpty()) { @@ -56,6 +89,11 @@ public class StackArray implements Stack { return stackArray[top]; } + /** + * Resizes the internal array to a new capacity. + * + * @param newSize the new size of the stack array + */ private void resize(int newSize) { @SuppressWarnings("unchecked") T[] newArray = (T[]) new Object[newSize]; System.arraycopy(stackArray, 0, newArray, 0, top + 1); @@ -63,21 +101,60 @@ public class StackArray implements Stack { maxSize = newSize; } + /** + * Checks if the stack is full. + * + * @return true if the stack is full, false otherwise + */ public boolean isFull() { return top + 1 == maxSize; } + /** + * Checks if the stack is empty. + * + * @return true if the stack is empty, false otherwise + */ @Override public boolean isEmpty() { return top == -1; } - @Override public void makeEmpty() { // Doesn't delete elements in the array but if you call - top = -1; // push method after calling makeEmpty it will overwrite previous values + /** + * Empties the stack, marking it as empty without deleting elements. Elements are + * overwritten on subsequent pushes. + */ + @Override + public void makeEmpty() { + top = -1; } + /** + * Returns the number of elements currently in the stack. + * + * @return the size of the stack + */ @Override public int size() { return top + 1; } + + /** + * Returns a string representation of the stack. + * + * @return a string representation of the stack + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("StackArray ["); + for (int i = 0; i <= top; i++) { + sb.append(stackArray[i]); + if (i < top) { + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } } diff --git a/src/test/java/com/thealgorithms/datastructures/stacks/StackArrayTest.java b/src/test/java/com/thealgorithms/datastructures/stacks/StackArrayTest.java index 3cda2f547..74de7ad64 100644 --- a/src/test/java/com/thealgorithms/datastructures/stacks/StackArrayTest.java +++ b/src/test/java/com/thealgorithms/datastructures/stacks/StackArrayTest.java @@ -21,11 +21,11 @@ class StackArrayTest { stack.push(4); stack.push(5); - Assertions.assertEquals(5, stack.pop()); // Stack follows LIFO, so 5 should be popped first - Assertions.assertEquals(4, stack.pop()); // Next, 4 should be popped - Assertions.assertEquals(3, stack.pop()); // Followed by 3 - Assertions.assertEquals(2, stack.pop()); // Then 2 - Assertions.assertEquals(1, stack.pop()); // Finally 1 + Assertions.assertEquals(5, stack.pop()); + Assertions.assertEquals(4, stack.pop()); + Assertions.assertEquals(3, stack.pop()); + Assertions.assertEquals(2, stack.pop()); + Assertions.assertEquals(1, stack.pop()); } @Test @@ -34,34 +34,34 @@ class StackArrayTest { stack.push(20); stack.push(30); - Assertions.assertEquals(30, stack.peek()); // Peek should return 30, the top of the stack - Assertions.assertEquals(3, stack.size()); // Size should remain 3 after peek + Assertions.assertEquals(30, stack.peek()); + Assertions.assertEquals(3, stack.size()); stack.pop(); - Assertions.assertEquals(20, stack.peek()); // After popping, peek should return 20 + Assertions.assertEquals(20, stack.peek()); } @Test void testIsEmpty() { - Assertions.assertTrue(stack.isEmpty()); // Initially, the stack should be empty + Assertions.assertTrue(stack.isEmpty()); stack.push(42); - Assertions.assertFalse(stack.isEmpty()); // After pushing an element, the stack should not be empty + Assertions.assertFalse(stack.isEmpty()); stack.pop(); - Assertions.assertTrue(stack.isEmpty()); // After popping the only element, the stack should be empty again + Assertions.assertTrue(stack.isEmpty()); } @Test void testResizeOnPush() { - StackArray smallStack = new StackArray<>(2); // Start with a small stack size + StackArray smallStack = new StackArray<>(2); smallStack.push(1); smallStack.push(2); - Assertions.assertTrue(smallStack.isFull()); // Initially, the stack should be full + Assertions.assertTrue(smallStack.isFull()); - smallStack.push(3); // This push should trigger a resize - Assertions.assertFalse(smallStack.isFull()); // The stack should no longer be full after resize - Assertions.assertEquals(3, smallStack.size()); // Size should be 3 after pushing 3 elements + smallStack.push(3); + Assertions.assertFalse(smallStack.isFull()); + Assertions.assertEquals(3, smallStack.size()); - Assertions.assertEquals(3, smallStack.pop()); // LIFO behavior check + Assertions.assertEquals(3, smallStack.pop()); Assertions.assertEquals(2, smallStack.pop()); Assertions.assertEquals(1, smallStack.pop()); } @@ -74,13 +74,13 @@ class StackArrayTest { stack.push(3); stack.push(4); - stack.pop(); // Removing elements should trigger a resize when less than 1/4 of the stack is used stack.pop(); stack.pop(); - Assertions.assertEquals(1, stack.size()); // After popping, only one element should remain + stack.pop(); + Assertions.assertEquals(1, stack.size()); stack.pop(); - Assertions.assertTrue(stack.isEmpty()); // The stack should be empty now + Assertions.assertTrue(stack.isEmpty()); } @Test @@ -90,32 +90,40 @@ class StackArrayTest { stack.push(3); stack.makeEmpty(); - Assertions.assertTrue(stack.isEmpty()); // The stack should be empty after calling makeEmpty - Assertions.assertThrows(IllegalStateException.class, stack::pop); // Popping from empty stack should throw exception + Assertions.assertTrue(stack.isEmpty()); + Assertions.assertThrows(IllegalStateException.class, stack::pop); } @Test void testPopEmptyStackThrowsException() { - Assertions.assertThrows(IllegalStateException.class, stack::pop); // Popping from an empty stack should throw an exception + Assertions.assertThrows(IllegalStateException.class, stack::pop); } @Test void testPeekEmptyStackThrowsException() { - Assertions.assertThrows(IllegalStateException.class, stack::peek); // Peeking into an empty stack should throw an exception + Assertions.assertThrows(IllegalStateException.class, stack::peek); } @Test void testConstructorWithInvalidSizeThrowsException() { - Assertions.assertThrows(IllegalArgumentException.class, () -> new StackArray<>(0)); // Size 0 is invalid - Assertions.assertThrows(IllegalArgumentException.class, () -> new StackArray<>(-5)); // Negative size is invalid + Assertions.assertThrows(IllegalArgumentException.class, () -> new StackArray<>(0)); + Assertions.assertThrows(IllegalArgumentException.class, () -> new StackArray<>(-5)); } @Test void testDefaultConstructor() { - StackArray defaultStack = new StackArray<>(); // Using default constructor - Assertions.assertEquals(0, defaultStack.size()); // Initially, size should be 0 + StackArray defaultStack = new StackArray<>(); + Assertions.assertEquals(0, defaultStack.size()); defaultStack.push(1); - Assertions.assertEquals(1, defaultStack.size()); // After pushing, size should be 1 + Assertions.assertEquals(1, defaultStack.size()); + } + + @Test + void testToString() { + stack.push(1); + stack.push(2); + stack.push(3); + Assertions.assertEquals("StackArray [1, 2, 3]", stack.toString()); } }