-
Notifications
You must be signed in to change notification settings - Fork 20.5k
Add tests for NodeStack and rework #6009
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 5 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
dbfe367
Add tests for NodeStack and rework
lorduke22 38e01f7
Fix clang format
lorduke22 1e97375
Fix build
lorduke22 3cd1ce4
Remove print function
lorduke22 c237423
Fix conflicts
lorduke22 465101f
Remove print function
lorduke22 008c224
Merge branch 'master' into add_tests_nodestack
lorduke22 6aa2ef0
Trigger CI/CD pipeline
lorduke22 9654d1a
Trigger CI/CD pipeline
lorduke22 f2fef25
Fix issue Infer build
lorduke22 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
162 changes: 55 additions & 107 deletions
162
src/main/java/com/thealgorithms/datastructures/stacks/NodeStack.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,161 +1,109 @@ | ||
package com.thealgorithms.datastructures.stacks; | ||
|
||
/** | ||
* Implementation of a stack using nodes. Unlimited size, no arraylist. | ||
* A stack implementation using linked nodes, supporting unlimited size without an ArrayList. | ||
* | ||
* @author Kyler Smith, 2017 | ||
* <p>Each node in the stack contains data of generic type {@code Item}, along with references | ||
* to the next and previous nodes, supporting typical stack operations. | ||
* | ||
* <p>The stack follows a Last-In-First-Out (LIFO) order where elements added last are | ||
* removed first. Supported operations include push, pop, and peek. | ||
* | ||
* @param <Item> the type of elements held in this stack | ||
*/ | ||
public class NodeStack<Item> { | ||
|
||
/** | ||
* Entry point for the program. | ||
* Node class representing each element in the stack. | ||
*/ | ||
public static void main(String[] args) { | ||
NodeStack<Integer> stack = new NodeStack<Integer>(); | ||
|
||
stack.push(3); | ||
stack.push(4); | ||
stack.push(5); | ||
System.out.println("Testing :"); | ||
stack.print(); // prints : 5 4 3 | ||
private class Node { | ||
Item data; | ||
Node previous; | ||
|
||
Integer x = stack.pop(); // x = 5 | ||
stack.push(1); | ||
stack.push(8); | ||
Integer y = stack.peek(); // y = 8 | ||
System.out.println("Testing :"); | ||
stack.print(); // prints : 8 1 4 3 | ||
|
||
System.out.println("Testing :"); | ||
System.out.println("x : " + x); | ||
System.out.println("y : " + y); | ||
Node(Item data) { | ||
this.data = data; | ||
this.previous = null; | ||
} | ||
} | ||
|
||
/** | ||
* Information each node should contain. | ||
* | ||
* @value data : information of the value in the node | ||
* @value head : the head of the stack | ||
* @value next : the next value from this node | ||
* @value previous : the last value from this node | ||
* @value size : size of the stack | ||
*/ | ||
private Item data; | ||
|
||
private static NodeStack<?> head; | ||
private NodeStack<?> previous; | ||
private static int size = 0; | ||
private Node head; // Top node in the stack | ||
private int size; // Number of elements in the stack | ||
|
||
/** | ||
* Constructors for the NodeStack. | ||
* Constructs an empty NodeStack. | ||
*/ | ||
public NodeStack() { | ||
} | ||
|
||
private NodeStack(Item item) { | ||
this.data = item; | ||
head = null; | ||
size = 0; | ||
} | ||
|
||
/** | ||
* Put a value onto the stack. | ||
* Pushes an item onto the stack. | ||
* | ||
* @param item : value to be put on the stack. | ||
* @param item the item to be pushed onto the stack | ||
*/ | ||
public void push(Item item) { | ||
NodeStack<Item> newNs = new NodeStack<Item>(item); | ||
|
||
if (this.isEmpty()) { | ||
NodeStack.setHead(new NodeStack<>(item)); | ||
newNs.setNext(null); | ||
newNs.setPrevious(null); | ||
} else { | ||
newNs.setPrevious(NodeStack.head); | ||
NodeStack.head.setNext(newNs); | ||
NodeStack.setHead(newNs); | ||
} | ||
|
||
NodeStack.setSize(NodeStack.getSize() + 1); | ||
Node newNode = new Node(item); | ||
newNode.previous = head; | ||
head = newNode; | ||
size++; | ||
} | ||
|
||
/** | ||
* Value to be taken off the stack. | ||
* Removes and returns the item at the top of the stack. | ||
* | ||
* @return item : value that is returned. | ||
* @return the item at the top of the stack, or {@code null} if the stack is empty | ||
* @throws IllegalStateException if the stack is empty | ||
*/ | ||
public Item pop() { | ||
Item item = (Item) NodeStack.head.getData(); | ||
|
||
NodeStack.setHead(NodeStack.head.getPrevious()); | ||
NodeStack.head.setNext(null); | ||
|
||
NodeStack.setSize(NodeStack.getSize() - 1); | ||
|
||
return item; | ||
if (isEmpty()) { | ||
throw new IllegalStateException("Cannot pop from an empty stack."); | ||
} | ||
Item data = head.data; | ||
head = head.previous; | ||
size--; | ||
return data; | ||
} | ||
|
||
/** | ||
* Value that is next to be taken off the stack. | ||
* Returns the item at the top of the stack without removing it. | ||
* | ||
* @return item : the next value that would be popped off the stack. | ||
* @return the item at the top of the stack, or {@code null} if the stack is empty | ||
* @throws IllegalStateException if the stack is empty | ||
*/ | ||
public Item peek() { | ||
return (Item) NodeStack.head.getData(); | ||
if (isEmpty()) { | ||
throw new IllegalStateException("Cannot peek from an empty stack."); | ||
} | ||
return head.data; | ||
} | ||
|
||
/** | ||
* If the stack is empty or there is a value in. | ||
* Checks whether the stack is empty. | ||
* | ||
* @return boolean : whether or not the stack has anything in it. | ||
* @return {@code true} if the stack has no elements, {@code false} otherwise | ||
*/ | ||
public boolean isEmpty() { | ||
return NodeStack.getSize() == 0; | ||
return head == null; | ||
} | ||
|
||
/** | ||
* Returns the size of the stack. | ||
* Returns the number of elements currently in the stack. | ||
* | ||
* @return int : number of values in the stack. | ||
* @return the size of the stack | ||
*/ | ||
public int size() { | ||
return NodeStack.getSize(); | ||
return size; | ||
} | ||
|
||
/** | ||
* Print the contents of the stack in the following format. | ||
* | ||
* <p> | ||
* x <- head (next out) y z <- tail (first in) . . . | ||
* Prints the contents of the stack from top to bottom. | ||
*/ | ||
public void print() { | ||
for (NodeStack<?> n = NodeStack.head; n != null; n = n.previous) { | ||
System.out.println(n.getData().toString()); | ||
Node current = head; | ||
while (current != null) { | ||
System.out.println(current.data); | ||
current = current.previous; | ||
} | ||
} | ||
|
||
private static void setHead(NodeStack<?> ns) { | ||
NodeStack.head = ns; | ||
} | ||
|
||
private void setNext(NodeStack<?> next) { | ||
} | ||
|
||
private NodeStack<?> getPrevious() { | ||
return previous; | ||
} | ||
|
||
private void setPrevious(NodeStack<?> previous) { | ||
this.previous = previous; | ||
} | ||
|
||
private static int getSize() { | ||
return size; | ||
} | ||
|
||
private static void setSize(int size) { | ||
NodeStack.size = size; | ||
} | ||
|
||
private Item getData() { | ||
return this.data; | ||
} | ||
} |
85 changes: 85 additions & 0 deletions
85
src/test/java/com/thealgorithms/datastructures/stacks/NodeStackTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package com.thealgorithms.datastructures.stacks; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertFalse; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
class NodeStackTest { | ||
|
||
@Test | ||
void testPush() { | ||
NodeStack<Integer> stack = new NodeStack<>(); | ||
stack.push(10); | ||
stack.push(20); | ||
assertEquals(20, stack.peek(), "Top element should be 20 after pushing 10 and 20."); | ||
} | ||
|
||
@Test | ||
void testPop() { | ||
NodeStack<String> stack = new NodeStack<>(); | ||
stack.push("First"); | ||
stack.push("Second"); | ||
assertEquals("Second", stack.pop(), "Pop should return 'Second', the last pushed element."); | ||
assertEquals("First", stack.pop(), "Pop should return 'First' after 'Second' is removed."); | ||
} | ||
|
||
@Test | ||
void testPopOnEmptyStack() { | ||
NodeStack<Double> stack = new NodeStack<>(); | ||
assertThrows(IllegalStateException.class, stack::pop, "Popping an empty stack should throw IllegalStateException."); | ||
} | ||
|
||
@Test | ||
void testPeek() { | ||
NodeStack<Integer> stack = new NodeStack<>(); | ||
stack.push(5); | ||
stack.push(15); | ||
assertEquals(15, stack.peek(), "Peek should return 15, the top element."); | ||
stack.pop(); | ||
assertEquals(5, stack.peek(), "Peek should return 5 after 15 is popped."); | ||
} | ||
|
||
@Test | ||
void testPeekOnEmptyStack() { | ||
NodeStack<String> stack = new NodeStack<>(); | ||
assertThrows(IllegalStateException.class, stack::peek, "Peeking an empty stack should throw IllegalStateException."); | ||
} | ||
|
||
@Test | ||
void testIsEmpty() { | ||
NodeStack<Character> stack = new NodeStack<>(); | ||
assertTrue(stack.isEmpty(), "Newly initialized stack should be empty."); | ||
stack.push('A'); | ||
assertFalse(stack.isEmpty(), "Stack should not be empty after a push operation."); | ||
stack.pop(); | ||
assertTrue(stack.isEmpty(), "Stack should be empty after popping the only element."); | ||
} | ||
|
||
@Test | ||
void testSize() { | ||
NodeStack<Integer> stack = new NodeStack<>(); | ||
assertEquals(0, stack.size(), "Size of empty stack should be 0."); | ||
stack.push(3); | ||
stack.push(6); | ||
assertEquals(2, stack.size(), "Size should be 2 after pushing two elements."); | ||
stack.pop(); | ||
assertEquals(1, stack.size(), "Size should be 1 after popping one element."); | ||
stack.pop(); | ||
assertEquals(0, stack.size(), "Size should be 0 after popping all elements."); | ||
} | ||
|
||
@Test | ||
void testPrint() { | ||
NodeStack<Integer> stack = new NodeStack<>(); | ||
stack.push(1); | ||
stack.push(2); | ||
stack.push(3); | ||
|
||
// Output verification would ideally be handled through a different means | ||
// but you can print as a basic check to confirm method runs without errors. | ||
stack.print(); | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.