Objectives

Upon finishing this assignment, you should be able to:

  • Implement a reference-based (node) implementation of a stack
  • Implement a stack in Java that supports generics
  • Solve problems using only the methods available in the Stack ADT

Part 1

1. Download all of the .java files found.

2. Read through the documentation provided in the Stack.java interface. There is a lot of information there that will help you set up your generic types when implementing the Stack interface.

3. Compile and run A4Tester.java. Work through implementing each stack method one at a time. Debug the method until all of the tests pass for that method before proceeding to the next method.

Part 2

1. For Part 2, you will complete the undo and redo functions in the WordProcessor class. The WordProcessor class is supposed to roughly simulate the undo and redo functions found in typical Word Processing programs. Note: You do not need to overthink the implementation here, one of the strengths of using a stack to solve a problem is that stack operations are considered intuitive and easy to use.

2. Although using the Word Processor should allow you to test the undo and redo methods, you may still want to write some tests to call undo and redo directly within the A4Tester.java class.

Starter Code

A4Node.java

public class A4Node< T >{

private T data;
protected A4Node< T > next;

public A4Node (T value) {
this.data = value;
this.next = null;
}

/*
* Purpose: get the data value of this Node
* Parameters: nothing
* Returns: T - the data value
*/
public T getData() {
return data;
}

/*
* Purpose: get the next node
* Parameters: nothing
* Returns: A4Node< T > - the next node
*/
public A4Node< T > getNext() {
return next;
}

/*
* Purpose: update the next reference for this node
* Parameters: A4Node< T > next - the new next
* Returns: void - nothing
*/
public void setNext(A4Node< T > next) {
this.next = next;
}

}

A4Stack.java

public class A4Stack< T > implements Stack< T > {

private A4Node< T > head;

public A4Stack() {
head = null;
}

public void push (T value) {
A4Node< T > n = new A4Node< T >(value);
n.setNext(head);
head = n;
}

public T pop() {
T data = null;
if (isEmpty()) {
;
} else {
data = head.getData();
A4Node temp = head;
head = head.getNext();
temp.setNext(null);
}
return data;
}

public void popAll() {
while (head != null) {
A4Node temp = head;
head = head.getNext();
temp.setNext(null);
}
}

public boolean isEmpty() {
if (head == null) {
return true;
}
return false;
}

public T peek() {
T data = null;
if (isEmpty()) {
;
} else {
data = head.getData();
}
return data;
}

/* The methods below have been completed for you.
Do not edit them in any way */

public String toString() {
String result = "{";
String separator = "";

A4Node< T > cur = head;
while (cur != null) {
result += separator + cur.getData().toString();
separator = ", ";
cur = cur.next;
}

result += "}";
return result;
}

public String getWords() {
return getWordsRec(head);
}

public String getWordsRec(A4Node< T > cur) {
if (cur == null) {
return "";
} else if (cur.next == null) {
return cur.getData().toString();
}else {
return getWordsRec(cur.next) + " " + cur.getData().toString();
}
}
}

A4Tester.java

public class A4Tester {

private static int testPassCount = 0;
private static int testCount = 0;

public static void main(String[] args) {
testStackOperations();
testStackIsGeneric();
testWordProcessor();

System.out.println("Passed " + testPassCount + " / " + testCount + " tests");
}

public static void testStackOperations() {
System.out.println("Stack Operations Tests:");
A4Stack< Integer > testStack = new A4Stack< Integer >();
Integer result = 0;

displayResults(testStack.isEmpty(), "stack initially empty");

testStack.push(2);
result = testStack.peek();
displayResults(!testStack.isEmpty(), "stack no longer empty");
displayResults(result.equals(2), "peek works after initial push");

//TODO: add more tests here

System.out.println();
}

public static void testStackIsGeneric() {
System.out.println("Stack Generics Tests:");
A4Stack< Integer > s1 = new A4Stack< Integer >();
A4Stack< String > s2 = new A4Stack< String >();
A4Stack< Double > s3 = new A4Stack< Double >();

Integer result1;
String result2;
Double result3;

s1.push(3);
s1.push(8);
s2.push("CSC");
s2.push("ENGR");
s3.push(5.5);
s3.push(9.1);

result1 = s1.pop();
result2 = s2.pop();
result3 = s3.pop();

displayResults(result1.equals(8), "Integer Stack");
displayResults(result2.equals("ENGR"), "String Stack");
displayResults(result3.equals(9.1), "Double Stack");

result1 = s1.peek();
result2 = s2.peek();
result3 = s3.peek();

displayResults(result1.equals(3), "Integer Stack");
displayResults(result2.equals("CSC"), "String Stack");
displayResults(result3.equals(5.5), "Double Stack");

//TODO: add more tests here

System.out.println();
}

public static void testWordProcessor() {
/* The following statement will begin the word processor
* simulation. You can comment it out to test the undo
* and redo methods individually if you wish, or just
* test them by running the simulation. */
WordProcessor.simulateWordProcessor();
}

public static void displayResults (boolean passed, String testName) {
testCount++;
if (passed) {
System.out.println ("Passed test: " + testName);
testPassCount++;
} else {
System.out.println ("Failed test: " + testName + " at line "
+ Thread.currentThread().getStackTrace()[2].getLineNumber());
}
}
}

Stack.java

interface Stack< T > {

/*
* Purpose: insert an item onto the top of the stack
* Parameters: int value - the value to insert
* Returns: void - Nothing
*/
public void push(T value);

/*
* Purpose: removes and returns the top item from the stack
* Parameters: None
* Returns: T - the data value of the element removed
* or null if the stack is empty
*/
public T pop();

/*
* Purpose: determines whether the stack is empty
* Parameters: None
* Returns: boolean - true if the stack is empty, false otherwise
*/
public boolean isEmpty();

/*
* Purpose: get the top item on the stack
* Parameters: None
* Returns: int - the data value of the top element
* or null if the stack is empty
*/
public T peek();

/*
* Purpose: removes all elements from the stack
* Parameters: None
* Returns: void - nothing
*/
public void popAll();
}

WordProcessor.java

import java.util.Scanner;

public class WordProcessor {
A4Stack< String > undo;
A4Stack< String > redo;

public WordProcessor() {
undo = new A4Stack< String >();
redo = new A4Stack< String >();
}

/*
* Purpose: undo most recent action, but record this
* action in redo just in case the user wants
* to redo it later
* Parameters: None
* Returns: boolean - true if undo was successful, false otherwise
*/
public boolean undo() {
// TODO: implement this!
return false; // so it compiles
}

/*
* Purpose: redo most recent action, but record this
* action in undo just in case the user wants
* to undo it later
* Parameters: None
* Returns: boolean - true if redo was successful, false otherwise
*/
public boolean redo() {
// TODO: implement this!
return false; // so it compiles
}

public void handleInput(String[] words) {
redo.popAll();
for (int i = 0; i < words.length; i++) {
undo.push(words[i]);
}
}

public void displayDocument() {
System.out.println("Document contents:");
System.out.println(undo.getWords());
System.out.println("n");
}

public static void simulateWordProcessor() {
WordProcessor w = new WordProcessor();
Scanner inputReader = new Scanner(System.in);
String userInput = "";
boolean done = false;

while (!done) {
System.out.println("Please do one of the following, and then hit enter:");
System.out.println(" - Enter text below");
System.out.println(" - Enter 1 to undo");
System.out.println(" - Enter 2 to redo");
System.out.println(" - Enter quit to quit");
System.out.print("Enter command: ");
userInput = inputReader.nextLine();
System.out.println("nn");
if (userInput.equals("quit")) {
done = true;
} else if (userInput.equals("1")) {
System.out.print("applying undo... ");
if (w.undo()) {
System.out.println("undo successfuln");
} else {
System.out.println("Nothing to undon");
}
} else if (userInput.equals("2")) {
System.out.print("applying redo... ");
if (w.redo()) {
System.out.println("redo successfuln");
} else {
System.out.println("Nothing to redon");
}
} else {
w.handleInput(userInput.split(" "));
}
w.displayDocument();
}

inputReader.close();

}

public static void main(String[] args) {
simulateWordProcessor();
}
}
Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.