Challenge 5

public class LinkedList<T> {
    private T data;
    private LinkedList<T> prevNode, nextNode;

    /**
     *  Constructs a new element
     *
     * @param  data, data of object
     * @param  node, previous node
     */
    public LinkedList(T data, LinkedList<T> node)
    {
        this.setData(data);
        this.setPrevNode(node);
        this.setNextNode(null);
    }

    /**
     *  Clone an object,
     *
     * @param  node  object to clone
     */
    public LinkedList(LinkedList<T> node)
    {
        this.setData(node.data);
        this.setPrevNode(node.prevNode);
        this.setNextNode(node.nextNode);
    }

    /**
     *  Setter for T data in DoubleLinkedNode object
     *
     * @param  data, update data of object
     */
    public void setData(T data)
    {
        this.data = data;
    }

    /**
     *  Returns T data for this element
     *
     * @return  data associated with object
     */
    public T getData()
    {
        return this.data;
    }

    /**
     *  Setter for prevNode in DoubleLinkedNode object
     *
     * @param node, prevNode to current Object
     */
    public void setPrevNode(LinkedList<T> node)
    {
        this.prevNode = node;
    }

    /**
     *  Setter for nextNode in DoubleLinkedNode object
     *
     * @param node, nextNode to current Object
     */
    public void setNextNode(LinkedList<T> node)
    {
        this.nextNode = node;
    }


    /**
     *  Returns reference to previous object in list
     *
     * @return  the previous object in the list
     */
    public LinkedList<T> getPrevious()
    {
        return this.prevNode;
    }

    /**
     *  Returns reference to next object in list
     *
     * @return  the next object in the list
     */
    public LinkedList<T> getNext()
    {
        return this.nextNode;
    }

}

public class Stack<T> {

    private LinkedList<T> upper;
    private int count;

    // constructor initiates null LinkedList<T> object + set size to 0
    public Stack() {
        this.upper = null;
        this.count = 0;
    }

    // push method for a new element to upper
    public void push(T data) {
        LinkedList<T> newNode = new LinkedList<T>(data, this.upper);
        this.upper = newNode;
        this.count++;
    }

    // peek method, return upper
    public T peek() {
        try {
            return this.upper.getData();
        } catch (NullPointerException e) {
            System.out.println("Stack is Empty");
            return null;
        }
    }

    // pop method, return and remove upper
    public T pop() {
        try {
            T data = this.upper.getData();
            this.upper = this.upper.getPrevious();
            this.count--;
            return data;
        } catch (NullPointerException e) {
            System.out.println("Stack is Empty");
            return null;
        }
    }

    public int getCount() {
        return this.count;
    }

    public boolean isEmpty() {
        return this.count == 0;
    }

    // toString method, from top to bottom
    public String toString() {
        String s = "[ ";
        LinkedList<T> currentNode = upper;

        while (currentNode != null) {
            s += currentNode.getData();
            currentNode = currentNode.getPrevious();
            if (currentNode != null) {
                s += ", ";
            }
        }
        s += " ]";
        System.out.println(s);
        return s;
    }

    
}
public class StackTest {
    public static void main(String[] args) {
        Stack<Integer> stackInt = new Stack<Integer>();
        System.out.println("Pushing the Stack:");
        for (int i = 1; i <= 5; i++) {
            stackInt.push(i);
            stackInt.toString();
        }
        System.out.println("");
        System.out.println("Popping the Stack:");
        System.out.println("");
        
        int count = stackInt.getCount();
        for (int i = 0; i <= count; i++) {
            System.out.print("Current Stack: ");
            stackInt.toString();
            System.out.println("Top Node: " + stackInt.peek());
            System.out.println("Nodes in Stack: " + stackInt.getCount());
            System.out.println("Stack Empty: " + stackInt.isEmpty());
            stackInt.pop();
            System.out.println("");
        }
    }
}
StackTest.main(null);
Pushing the Stack:
[ 1 ]
[ 2, 1 ]
[ 3, 2, 1 ]
[ 4, 3, 2, 1 ]
[ 5, 4, 3, 2, 1 ]

Popping the Stack:

Current Stack: [ 5, 4, 3, 2, 1 ]
Top Node: 5
Nodes in Stack: 5
Stack Empty: false

Current Stack: [ 4, 3, 2, 1 ]
Top Node: 4
Nodes in Stack: 4
Stack Empty: false

Current Stack: [ 3, 2, 1 ]
Top Node: 3
Nodes in Stack: 3
Stack Empty: false

Current Stack: [ 2, 1 ]
Top Node: 2
Nodes in Stack: 2
Stack Empty: false

Current Stack: [ 1 ]
Top Node: 1
Nodes in Stack: 1
Stack Empty: false

Current Stack: [  ]
Stack is Empty
Top Node: null
Nodes in Stack: 0
Stack Empty: true
Stack is Empty

public class StackMerger<T> {
    private final Stack<T> s1;
    private final Stack<T> s2;
    private Stack<T> s3;
    
    // constructor for Stackmerger
    public StackMerger(Stack<T> s1, Stack<T> s2) {
        this.s1 = s1;
        this.s2 = s2;
        this.merge(s1, s2);
    }
    
    public void merge(Stack<T> s1, Stack<T> s2) {
        Stack<T> mergedStack = new Stack<T>();
        // if both stacks are not empty, 
        while (!s1.isEmpty() && !s2.isEmpty()) {
            mergedStack.push(s1.pop());
            mergedStack.push(s2.pop());
        }
        // if s1 is empty, pop from s2 and push to mergedStack
        while (!s2.isEmpty()) {
            mergedStack.push(s2.pop());
        }
        // if s2 is empty, pop from s1 and push to mergedStack
        while (!s1.isEmpty()) {
            mergedStack.push(s1.pop());
        }
        s3 = mergedStack;
    }

    // toString method using Stack<T> toString
    public String toString() {
        return s3.toString();
    }
}

public class TesterTwo {
    public static void main(String[] args) {
        // test stack with Integer wrapper class
        Stack<Integer> stack1 = new Stack<Integer>();
        for (int i = 1; i <=5; i++){
            stack1.push(i);
        }
        stack1.toString();

        Stack<Integer> stack2 = new Stack<Integer>();
        for (int i = 6; i <=10; i++){
            stack2.push(i);
        }
        stack2.toString();

        StackMerger<Integer> stack12 = new StackMerger<Integer>(stack1, stack2);
        stack12.toString();
    }
}

TesterTwo.main(null);
[ 5, 4, 3, 2, 1 ]
[ 10, 9, 8, 7, 6 ]
[ 6, 1, 7, 2, 8, 3, 9, 4, 10, 5 ]