I am working to write code to Evaluate the given postfix expression. I have wrote a code, but one of the junit test doesn´t go through. How should i write that "expr contains too few operands". In the evalute I use a stack.
TODO: help to correct the "evaluate(String expr) throws ExpressionException ()" method so all the test in the testclass goes through.
EDIT: The test that i need help withy is the only in the JUNIT test class.
Interface stack:
/**
* A interface of stack
*/
public interface Stack <T> {
/**
* Adds the element to the top of the stack.
*/
void push (T elem);
/**
* Removes and returns the top element in stack,
* that is the element that was last added.
* Throws an EmptyStackException if stack is empty.
*/
T pop();
/**
* Returns the top element in the stack without removing it.
* Throws an EmptyStackException if stack is empty.
*/
T top();
/**
* Returns the number of elements in stack.
* #return the number of elements.
*/
int size();
/**
* Returns true if the stack is empty.
* #return true.
*/
boolean isEmpty();
}
Linkedlist implements stack:
import java.util.EmptyStackException;
import java.util.NoSuchElementException;
/**
* A singly linked list.
*
*/
public class LinkedList<T> implements Stack <T> {
private ListElement<T> first; // First element in list.
private ListElement<T> last; // Last element in list.
private int size; // Number of elements in list.
/**
* A list element.
*/
private static class ListElement<T>{
public T data;
public ListElement<T> next;
public ListElement(T data) {
this.data = data;
this.next = null;
}
}
/**
* Creates an empty list.
*/
public LinkedList() {
this.first = null;
this.last = null;
this.size = 0;
}
/**
* Inserts the given element at the beginning of this list.
*
* #param element An element to insert into the list.
*/
public void addFirst(T element) {
ListElement<T> firstElement = new ListElement<>(element);
if (this.size == 0){
this.first = firstElement;
this.last = firstElement;
}
else{
firstElement.next = this.first;
this.first = firstElement;
}
this.size ++;
}
/**
* Inserts the given element at the end of this list.
*
* #param element An element to insert into the list.
*/
public void addLast(T element) {
ListElement<T> lastElement = new ListElement<>(element);
if(this.size ==0){
this.first = lastElement;
}
else{
this.last.next = lastElement;
}
this.last = lastElement;
this.size ++;
}
/**
* #return The head of the list.
* #throws NoSuchElementException if the list is empty.
*/
public T getFirst() {
if (this.first != null){
return this.first.data;
}
else{
throw new NoSuchElementException();
}
}
/**
* #return The tail of the list.
* #throws NoSuchElementException if the list is empty.
*/
public T getLast() {
if(this.last != null){
return this.last.data;
}
else{
throw new NoSuchElementException();
}
}
/**
* Returns an element from a specified index.
*
* #param index A list index.
* #return The element at the specified index.
* #throws IndexOutOfBoundsException if the index is out of bounds.
*/
public T get(int index) {
if(index < 0|| index >= this.size){
throw new IndexOutOfBoundsException();
}
else{
ListElement<T>element = this.first;
for(int i = 0; i < index; i++){
element = element.next;
}
return element.data;
}
}
/**
* Removes the first element from the list.
*
* #return The removed element.
* #throws NoSuchElementException if the list is empty.
*/
public T removeFirst() {
if(this.first != null || this.size != 0){
ListElement<T> list = this.first;
this.first = first.next;
size --;
return list.data;
}
else{
throw new NoSuchElementException();
}
}
/**
* Removes all of the elements from the list.
*/
public void clear() {
this.first = null;
this.last = null;
this.size =0;
}
/**
* Adds the element to the top of the stock.
* #param elem
*/
#Override
public void push(T elem) {
ListElement <T> list = new ListElement<>(elem);
if( first == null){
first = list;
last = first;
} else{
list.next = first;
first = list;
}
size ++;
}
/**
* Removes and returns the top element in stack,
* that is the element that was last added.
* Throws an EmptyStackException if stack is empty.
* #return the top element in the stack.
*/
#Override
public T pop(){
if(isEmpty()){
throw new EmptyStackException();
}else{
ListElement <T> list = first;
first = first.next;
size --;
return list.data;
}
}
/**
* returns the top element in the stack without removing it.
* Throws an EmptyStackException if stack is empty.
* #return the top element.
*/
#Override
public T top() {
if(isEmpty()){
throw new EmptyStackException();
}else{
return first.data;
}
}
/**
* Returns the number of elements in the stock
* #return The number of elements in the stock.
*/
public int size() {
return this.size;
}
/**
* Note that by definition, the list is empty if both first and last
* are null, regardless of what value the size field holds (it should
* be 0, otherwise something is wrong).
*
* #return <code>true</code> if this list contains no elements.
*/
public boolean isEmpty() {
return first == null && last == null;
}
/**
* Creates a string representation of this list. The string
* representation consists of a list of the elements enclosed in
* square brackets ("[]"). Adjacent elements are separated by the
* characters ", " (comma and space). Elements are converted to
* strings by the method toString() inherited from Object.
*
* Examples:
* "[1, 4, 2, 3, 44]"
* "[]"
*
* #return A string representing the list.
*/
public String toString() {
ListElement<T> listOfElements = this.first;
String returnString = "[";
while(listOfElements != null) {
returnString += listOfElements.data;
if(listOfElements.next != null){
returnString += ", ";
}
listOfElements = listOfElements.next;
}
returnString += "]";
return returnString;
}
}
Postfix class:
import java.util.Scanner;
import java.util.Stack;
/**
* The Postfix class implements an evaluator for integer postfix expressions.
*
* Postfix notation is a simple way to define and write arithmetic expressions
* without the need for parentheses or priority rules. For example, the postfix
* expression "1 2 - 3 4 + *" corresponds to the ordinary infix expression
* "(1 - 2) * (3 + 4)". The expressions may contain decimal 32-bit integer
* operands and the four operators +, -, *, and /. Operators and operands must
* be separated by whitespace.
*
*/
public class Postfix {
public static class ExpressionException extends Exception {
public ExpressionException(String message) {
super(message);
}
}
/**
* Evaluates the given postfix expression.
*
* #param expr Arithmetic expression in postfix notation
* #return The value of the evaluated expression
* #throws ExpressionException if the expression is wrong
*/
public static int evaluate(String expr) throws ExpressionException {
expr = expr.trim();
String[] tokens = expr.split("\\s+");
if(expr.matches("(\\+)|(\\-)|(\\*)|(\\/)")){
throw new ExpressionException("");
}
LinkedList<Integer> stack = new LinkedList<>();
for(String token: tokens) {
if(isInteger(token)) {
int number = Integer.parseInt(token);
stack.push(number);
}
else if(isOperator(token)) {
String operator = token;
int b = stack.pop();
int a = stack.pop();
if(token.equals("+")){
stack.push(a+b);
} else if (token.equals("-")){
stack.push(a-b);
}
else if(token.equals("/")){
if( b == 0){
throw new ExpressionException("");
}
stack.push(a/b);
} else if(token.equals("*")){
stack.push(a*b);
}
}
else {
throw new ExpressionException("");
}
}
if(stack.size() != 1){
throw new ExpressionException("");
}
int result = stack.pop();
if(stack.isEmpty()) {
throw new ExpressionException("");
}
return result;
}
/**
* Returns true if s is an operator.
*
* A word of caution on using the String.matches method: it returns true
* if and only if the whole given string matches the regex. Therefore
* using the regex "[0-9]" is equivalent to "^[0-9]$".
*
* An operator is one of '+', '-', '*', '/'.
*/
private static boolean isOperator(String s) {
return s.matches("[-+*/]");
}
/**
* Returns true if s is an integer.
*
* A word of caution on using the String.matches method: it returns true
* if and only if the whole given string matches the regex. Therefore
* using the regex "[0-9]" is equivalent to "^[0-9]$".
*
* We accept two types of integers:
*
* - the first type consists of an optional '-'
* followed by a non-zero digit
* followed by zero or more digits,
*
* - the second type consists of an optional '-'
* followed by a single '0'.
*/
private static boolean isInteger(String s) {
return s.matches("(((\\-)*?[1-9](\\d+)*)|(\\-)*?0)");
}
}
Junit class
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import java.util.Arrays;
/**
* Test class for Postfix
*
*/
public class PostfixTest {
#Rule public Timeout globalTimeout = Timeout.seconds(5);
#Test
public void evaluateExceptionWhenExprContainsTooFewOperands() {
String[] expressions = {"1 +", " 1 2 + +"};
assertExpressionExceptionOnAll(expressions);
}
}
Your pop() method will throw an exception when the stack is empty (which you can catch) and your isEmpty() method will return true when the stack is empty. You can also use the size() method to check the number of items on the stack. As an example, you can use code like this to check if there are enough values to run your operand:
// ...
else if(isOperator(token)) {
String operator = token;
if (stack.size() < 2) {
throw new ExpressionException("There are not enough values on the stack to perform the operation");
}
int b = stack.pop();
int a = stack.pop();
// ...
Related
I've been trying to program a LinkedList implementation of a Stack and of a Queue. Whenever I run them however, I get an error letting me know that the list is empty when I try and pop/dequeue anything. The thing is, if I call .toString() on the list, even RIGHT before the pop/dequeue command, I can see that they're not. I can't myself see anything wrong with my pop/dequeue implementation, but perhaps you fine folks can help me out.
LinkedList.java
package jsjf;
import jsjf.exceptions.*;
import java.util.*;
/**
* LinkedList represents a linked implementation of a list.
*
* #author Java Foundations
* #version 4.0
*/
public class LinkedList<T> implements ListADT<T>, Iterable<T>
{
protected int count;
protected LinearNode<T> head, tail;
protected int modCount;
/**
* Creates an empty list.
*/
public LinkedList()
{
count = 0;
head = tail = null;
modCount = 0;
}
/**
* Adds a new element to the end of the list.
*
* #param element the element to add.
*/
public void add(T element) {
// If the list is empty...
if(this.tail == null){
// Creates a new node for the new element.
LinearNode<T> newElement = new LinearNode(element);
// Assigns the new node to be the head and the tail.
this.tail = this.head = newElement;
}
// Otherwise...
else {
// Temporary caches the old tail.
LinearNode<T> temp = this.tail;
// Creates a new node for the new element.
LinearNode<T> newElement = new LinearNode(element);
// Assigns the new node to follow the old tail.
temp.setNext(newElement);
// Assigns the old tail to precede the new node.
newElement.setPrevious(temp);
// Assigns the new node to be the tail.
this.tail = newElement;
}
}
/**
* Adds a new element at a specific index, bumping the current element at
* that index to the next index.
*
* #param index the index to add to.
* #param element the element to add.
*/
public void add(int index, T element) {
// Find the node at the index requested.
LinearNode<T> desiredIndex = this.head;
for(int i = 1; i <= index; i++){
desiredIndex = desiredIndex.getNext();
}
// Hold the previous element of the old element.
LinearNode<T> prev = desiredIndex.getPrevious();
// Create a new node for the new element.
LinearNode<T> newElement = new LinearNode(element);
// Assign prev to precede the new element.
newElement.setPrevious(prev);
// Assign the old element to follow the new element.
newElement.setNext(desiredIndex);
// Assign the new element to precede the old element.
desiredIndex.setPrevious(newElement);
}
/**
* Returns an element from a specific index, without removing it.
*
* #param index the index to check.
* #return the element at that index.
*/
public T get(int index) {
// Find the node at the index requested.
LinearNode<T> desiredIndex = this.head;
for(int i = 1; i <= index; i++){
desiredIndex = desiredIndex.getNext();
}
// Return that element.
return desiredIndex.getElement();
}
/** Removes the first element in this list and returns a reference
* to it. Throws an EmptyCollectionException if the list is empty.
*
* #return a reference to the first element of this list
* #throws EmptyCollectionException if the list is empty
*/
public T removeFirst() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException("list");
T result = head.getElement();
head = head.getNext();
count--;
if(isEmpty())
tail = null;
modCount++;
return result;
}
/**
* Removes the last element in this list and returns a reference
* to it. Throws an EmptyCollectionException if the list is empty.
*
* #return the last element in this list
* #throws EmptyCollectionException if the list is empty
*/
public T removeLast() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException("list");
T result = tail.getElement();
tail = tail.getPrevious();
count--;
if(isEmpty())
tail = null;
modCount++;
return result;
}
/**
* Removes the first instance of the specified element from this
* list and returns a reference to it. Throws an EmptyCollectionException
* if the list is empty. Throws a ElementNotFoundException if the
* specified element is not found in the list.
*
* #param targetElement the element to be removed from the list
* #return a reference to the removed element
* #throws EmptyCollectionException if the list is empty
* #throws ElementNotFoundException if the target element is not found
*/
public T remove(T targetElement) throws EmptyCollectionException,
ElementNotFoundException
{
if (isEmpty())
throw new EmptyCollectionException("LinkedList");
boolean found = false;
LinearNode<T> previous = null;
LinearNode<T> current = head;
while (current != null && !found)
if (targetElement.equals(current.getElement()))
found = true;
else
{
previous = current;
current = current.getNext();
}
if (!found)
throw new ElementNotFoundException("LinkedList");
if (size() == 1) // only one element in the list
head = tail = null;
else if (current.equals(head)) // target is at the head
head = current.getNext();
else if (current.equals(tail)) // target is at the tail
{
tail = previous;
tail.setNext(null);
}
else // target is in the middle
previous.setNext(current.getNext());
count--;
modCount++;
return current.getElement();
}
/**
* Changes the element at a specific index.
*
* #param index the index to change.
* #param element the element to change to.
*/
public void set(int index, T element) {
// Find the node at the index requested.
LinearNode<T> desiredIndex = this.head;
for(int i = 1; i <= index; i++){
desiredIndex = desiredIndex.getNext();
}
// Change the element at that index.
desiredIndex.setElement(element);
}
/**
* Returns the first element in this list without removing it.
*
* #return the first element in this list
* #throws EmptyCollectionException if the list is empty
*/
public T first() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException("list");
T result = head.getElement();
return result;
}
/**
* Returns the last element in this list without removing it.
*
* #return the last element in this list
* #throws EmptyCollectionException if the list is empty
*/
public T last() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException("list");
T result = tail.getElement();
return result;
}
/**
* Returns true if the specified element is found in this list and
* false otherwise. Throws an EmptyCollectionException if the list
* is empty.
*
* #param targetElement the element that is sought in the list
* #return true if the element is found in this list
* #throws EmptyCollectionException if the list is empty
*/
public boolean contains(T targetElement) throws
EmptyCollectionException
{
if(isEmpty())
throw new EmptyCollectionException("list");
boolean found = false;
LinearNode<T> previous = null;
LinearNode<T> current = head;
while (current != null && !found)
if (targetElement.equals(current.getElement()))
found = true;
else
{
previous = current;
current = current.getNext();
}
if (!found)
throw new ElementNotFoundException("LinkedList");
return found;
}
/**
* Returns true if this list is empty and false otherwise.
*
* #return true if the list is empty, false otherwise
*/
public boolean isEmpty()
{
return (count == 0);
}
/**
* Returns the number of elements in this list.
*
* #return the number of elements in the list
*/
public int size()
{
return count;
}
/**
* Returns a string representation of this list.
*
* #return a string representation of the list
*/
public String toString()
{
String result = "";
LinearNode current = head;
while (current != null)
{
result = result + current.getElement() + "\n";
current = current.getNext();
}
return result;
}
/**
* Returns an iterator for the elements in this list.
*
* #return an iterator over the elements of the list
*/
public Iterator<T> iterator()
{
return new LinkedListIterator();
}
/**
* LinkedIterator represents an iterator for a linked list of linear nodes.
*/
private class LinkedListIterator implements Iterator<T>
{
private int iteratorModCount; // the number of elements in the collection
private LinearNode<T> current; // the current position
/**
* Sets up this iterator using the specified items.
*
* #param collection the collection the iterator will move over
* #param size the integer size of the collection
*/
public LinkedListIterator()
{
current = head;
iteratorModCount = modCount;
}
/**
* Returns true if this iterator has at least one more element
* to deliver in the iteration.
*
* #return true if this iterator has at least one more element to deliver
* in the iteration
* #throws ConcurrentModificationException if the collection has changed
* while the iterator is in use
*/
public boolean hasNext() throws ConcurrentModificationException
{
if (iteratorModCount != modCount)
throw new ConcurrentModificationException();
return (current != null);
}
/**
* Returns the next element in the iteration. If there are no
* more elements in this iteration, a NoSuchElementException is
* thrown.
*
* #return the next element in the iteration
* #throws NoSuchElementException if the iterator is empty
*/
public T next() throws ConcurrentModificationException
{
if (!hasNext())
throw new NoSuchElementException();
T result = current.getElement();
current = current.getNext();
return result;
}
/**
* The remove operation is not supported.
*
* #throws UnsupportedOperationException if the remove operation is called
*/
public void remove() throws UnsupportedOperationException
{
throw new UnsupportedOperationException();
}
}
}
LinkedListQueue.java
package jsjf;
public class LinkedListQueue<T> implements QueueADT<T> {
LinkedList queue = new LinkedList();
/**
* Adds the specified element to the back of this queue.
*
* #param element generic element to be pushed onto queue.
*/
public void enqueue(T element) {
queue.add(element);
}
/**
* Removes the element from the front of the queue and returns it.
*
* #return the element from the front of the queue.
*/
public T dequeue() {
return (T) queue.removeFirst();
}
/**
* Returns the front element, without removing it.
*
* #return the element at the front of the queue.
*/
public T first() {
return (T) queue.first();
}
/**
* Returns true if the queue is empty.
*
* #return the boolean value of this queue being empty.
*/
public boolean isEmpty() {
if(queue.isEmpty())
return true;
return false;
}
/**
* Returns the number of elements contained in the queue.
*
* #return the number of elements contained in the queue.
*/
public int size() {
return queue.size();
}
/**
* Returns the queue as a string.
*
* #return the queue as a string.
*/
public String toString() {
return queue.toString();
}
}
LinkedListStack.java
package jsjf;
public class LinkedListStack<T> implements StackADT<T> {
LinkedList stack = new LinkedList();
/**
* Adds the specified element to the top of this stack.
*
* #param element generic element to be pushed onto stack.
*/
public void push(T element) {
stack.add(element);
}
/**
* Removes the element from the top of the stack and returns it.
*
* #return the element from the top of the stack.
*/
public T pop() {
return (T) stack.removeLast();
}
/**
* Returns the top element, without removing it.
*
* #return the element at the top of the stack.
*/
public T peek() {
return (T) stack.last();
}
/**
* Returns true if the stack is empty.
*
* #return the boolean value of this stack being empty.
*/
public boolean isEmpty() {
if(stack.isEmpty())
return true;
return false;
}
/**
* Returns the number of elements contained in the stack.
*
* #return the number of elements contained in the stack.
*/
public int size() {
return stack.size();
}
/**
* Returns the stack as a string.
*
* #return the stack as a string.
*/
public String toString() {
return stack.toString();
}
}
Driver.java
package jsjf;
public class Driver {
public static void main(String[] args) {
// Instantiate the array based structures.
ArrayListQueue arrayQueue = new ArrayListQueue();
ArrayListStack arrayStack = new ArrayListStack();
// Instantiate the link based structures.
LinkedListQueue linkedQueue = new LinkedListQueue();
LinkedListStack linkedStack = new LinkedListStack();
// An integer to hold reference to a data piece to be pushed to the structures.
int data;
// Randomly generate a piece of data, and pass it to the structures.
for(int i = 0; i < 25; i++){
data = (int)(Math.random() * 50);
arrayQueue.enqueue(data);
arrayStack.push(data);
linkedQueue.enqueue(data);
linkedStack.push(data);
}
System.out.print("Array Queue: ");
for(int i = 0; i < 25; i++){
System.out.print(arrayQueue.dequeue() + " ");
}
System.out.println();
System.out.print("Array Stack: ");
for(int i = 0; i < 25; i++){
System.out.print(arrayStack.pop() + " ");
}
System.out.println();
System.out.print("\n\nLinked Stack as string: " + linkedStack.toString() + "\n\n");
System.out.print("Linked Stack: ");
for(int i = 0; i < 25; i++){
System.out.print(linkedStack.pop() + " ");
}
System.out.println();
System.out.print("Linked Queue: " + linkedQueue.toString());
System.out.print("Linked Queue: ");
for(int i = 0; i < 25; i++){
System.out.print(linkedQueue.dequeue() + " ");
}
System.out.println();
}
}
When I run Driver.java, I get the following output.
Array Queue: 45 12 25 40 31 32 14 16 14 26 3 25 22 26 29 6 13 12 30 10 46 10 11 3 11
Array Stack: 11 3 11 10 46 10 30 12 13 6 29 26 22 25 3 26 14 16 14 32 31 40 25 12 45
Linked Stack as string: 45
12
25
40
31
32
14
16
14
26
3
25
22
26
29
6
13
12
30
10
46
10
11
3
11
Linked Stack: Exception in thread "main" jsjf.exceptions.EmptyCollectionException: The list is empty.
at jsjf.LinkedList.removeLast(LinkedList.java:135)
at jsjf.LinkedListStack.pop(LinkedListStack.java:24)
at jsjf.Driver.main(Driver.java:46)
Looks like you don't increment count in your add methods for the linked list, but are using count to determine if its empty or not.
So in my assignment, I have to implement a dropout stack in Java. A drop-out stack behaves like a stack in every respect except that if the stack size is n, then when the n+1 element is pushed, the first element is lost. In my case, I have set n=5. My code is running fine, but when I add more elements after the 5th element, the element at the bottom is not being removed. It just keeps stacking the new ones on top like a normal stack. Please help me understand how to fix this. Here is my code for the stack implementation:
/**
* Represents a linked implementation of a stack.
*
* #author Java Foundations
* #version 4.0
*/
public class DropOutStack<T> implements StackADT<T>
{
private int count; //number of elements in the stack
private LinearNode<T> top;
/*Declares the maximum number of elements in the stack*/
private final int n = 5;//max size
private LinearNode<T> prev;
private LinearNode<T> curr;
/**
* Creates an empty stack.
*/
public DropOutStack()
{
count = 0;
top = null;
}
/**
* Adds the specified element to the top of this stack.
* #param element element to be pushed on stack
*/
public void push(T element)
{
LinearNode<T> temp = new LinearNode<T>(element);
/*Verifies that the number of elements in the stack is
* less than n. If yes, adds the new element to the stack*/
if (count < n) {
temp.setNext(top);
top = temp;
count++;
}
/*Verifies if the number of elements in the stack is greater
* than or equal to n or not, and that the n is not equal to one.
* If yes, removes the first element from the stack and adds
* the new element to the stack*/
else if(count>=n && n!=1) {
prev = top;
curr = top.getNext();
while(curr != null) {
prev = prev.getNext();
curr = curr.getNext();
}
prev.setNext(null);
count--;
push(element);
}
else //if n=1
{
top.setElement(element);
}
}
/**
* Removes the element at the top of this stack and returns a
* reference to it.
* #return element from top of stack
* #throws EmptyCollectionException if the stack is empty
*/
public T pop() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException("stack");
T result = top.getElement();
top = top.getNext();
count--;
return result;
}
/**
* Returns a reference to the element at the top of this stack.
* The element is not removed from the stack.
* #return element on top of stack
* #throws EmptyCollectionException if the stack is empty
*/
public T peek() throws EmptyCollectionException
{
if (isEmpty())
throw new EmptyCollectionException("stack");
T result = top.getElement();
return result;
}
/**
* Returns true if this stack is empty and false otherwise.
* #return true if stack is empty
*/
public boolean isEmpty()
{
return (count ==0);
}
/**
* Returns the number of elements in this stack.
* #return number of elements in the stack
*/
public int size()
{
return count;
}
/**
* Returns a string representation of this stack.
* #return string representation of the stack
*/
public String toString()
{
String result = "";
LinearNode<T> current = top;
while (current != null) {
result = current.getElement() + "\n" + result;
current = current.getNext();
}
return result;
}
}
The issue is that you are iterating too far over the linked list in your else if (count >= n && n != 1) block.
Currently you terminate when curr == null, but if curr is null then prev is the last node in the list, who's next value is already null (curr).
To resolve this, change the loop condition to curr.getNext() != null. Since you always want to push the element, just do that at the end and simplify the logic, given the precondition that n (the max size [poor name]) should be at least 1.
/**
* #pre. n >= 1
*/
public void push(T element) {
if (count >= n) {
assert top != null;
prev = null;
curr = top;
while (curr.getNext() != null) {
prev = curr;
curr = curr.getNext();
}
if (prev != null) {
prev.setNext(null);
} else {
top = null;
}
count--;
}
LinearNode<T> temp = new LinearNode<>(element);
temp.setNext(top);
top = temp;
count++;
}
What i need to do in this assignment, is to implement the given methods from the interface. If you could check and give me some feedback on what i've delivered so far, would be very much appreciated.
I am still missing one method unfortunately, public T getNext8thElementOf(int pos). Does anyone has an idea on how to implement it?
/**
* A simple list interface
* #param <T> The type of list element
*/
public interface ISpeedList<T> {
/**
* Returns the current number of elements in the list
*
* #return Current number of elements in the list
*/
public int size();
/**
* Inserts an element at the beginning of the list
*
* #param item Item to be inserted
*/
public void prepend(T item);
/**
* Returns the element at the specified position in the list
*
* #param pos The position of the element in the list starting from 0
*
* #return The specified element in the list
*
* #throws IndexOutOfBoundsException If the requested element is out of
* range
*/
public T getElementAt(int pos);
/**
* Returns the next 8th element of the specified element in the list
*
* #param pos The position of the specified element in the list starting
* from 0
*
* #return The next 8th element of the specified element
*
* #throws IndexOutOfBoundsException If the requested element is out of
* range
*/
public T getNext8thElementOf(int pos);
}
public class SpeedList<T> implements ISpeedList<T> {
/**
* Doubly-linked node class, completely private to the List class,
* as clients don't care about the implementation of the list.
*/
private class Node {
T item;
Node next;
Node previous;
Node(T item, Node next, Node previous) {
this.item = item;
this.next = next;
this.previous = previous;
}
}
/**
* The list itself maintains only a reference to its "header" node.
* The header is a node that does not store any data. Its 'next'
* field points to the first item in the list and its 'previous'
* field points to the last item. This makes all insertions and
* deletions uniform, even at the beginning and the end of the list!
*/
private Node header = new Node(null, null, null);
/**
* The number of items in the list, stored to make size() O(1).
*/
private int size = 0;
/**
* Returns the number of items in the list.
*/
#Override
public int size() {
return size;
}
/**
* Inserts <code>item</code> as the new first item.
*/
#Override
public void prepend(T item) {
addBefore(item, header.next);
}
/**
* Returns the item at the given index position.
*
* #throws IndexOutOfBoundsException
* if index not in [0,size).
*/
#Override
public T getElementAt(int pos) {
return nodeAt(pos).item;
}
#Override
public T getNext8thElementOf(int pos) {
// TODO Auto-generated method stub
return null;
}
//
// PRIVATE HELPER METHODS
//
private Node nodeAt(int pos) {
if (pos < 0 || pos >= size) {
throw new IndexOutOfBoundsException(pos + " for size " + size);
}
Node n = header;
for (int i = 0; i <= pos; i++) {
n = n.next;
}
return n;
}
private void addBefore(T o, Node n) {
Node newNode = new Node(o, n, n.previous);
newNode.previous.next = newNode;
newNode.next.previous = newNode;
size++;
}
}
Is that what you want?
#Override
public T getNext8thElementOf(int pos) {
int eight = 8;
Node nodo = this.nodeAt(pos);
while(eight > 0) {
eight--;
nodo = nodo.next;
}
return nodo.item;
}
I've been trying to define an immutable ConsList in Java, somewhat like how Lists work in Scala. Each prepending creates a new view of the list (starting with the new head) and returns it. Here's what I have so far, which all compiles and runs correctly.
package common.dataStructures;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Objects;
/**
* An immutable collection representing a Cons List.
* All Cons Lists are terminated with a Nil element (no tail, no value),
* but this element is hidden from iteration and stringing when there
* are non-nil elements in the list.
* <br><br>
* Because the List is immutable, different lists can be branched off of a shared
* tail without altering the tail. This makes the ConsList useful in some algorithms
* that require exploring different possibility chains without altering earlier
* sub-chains.
*
* #param <E> - the generic type of elements stored within the lst.
* No methods are ever called on elements of type E, so no requirements
* are made of the type.
* #author Mshnik
*/
public class ConsList<E> implements Iterable<E> {
/**
* A string used for toString implementations for the Nil element of
* a Cons List
*/
public static final String NIL_STRING = "_NIL_";
/**
* The tail of this List.
* If this is Nil, tail is null. Otherwise, this is another ConsList
* of one smaller size.
*/
private final ConsList<E> tail;
/**
* The value stored in the head of this list.
* If this is Nil, value is null. Otherwise the value may be null,
* or the value stored in the head.
*/
public final E val;
/**
* The size of this list. Because ConsLists are immutable, this size
* value is immutable. If this is Nil, size is 0. Otherwise, size
* is some positive, non-zero value
*/
public final int size;
/**
* Initializes an empty (NIL) ConsList, with tail = null, val = null,
* size = 0. <br>
* A Nil element is required to be at the end of every ConsList,
* so this constructor is used to start any ConsList. Elements are then
* cons (prepended) on to this element to build a list.
*/
public ConsList() {
val = null;
tail = null;
size = 0;
}
/**
* Creates a new head of a list
*
* #param val - the value to store in the head of this list
* #param tail - the tail of this list, an existing ConsList
* #param size - the size of this list
*/
private ConsList(E val, ConsList<E> tail, int size) {
this.val = val;
this.size = size;
this.tail = tail;
if (val == null || tail == null || size < 1)
throw new RuntimeException("Illegal ConsList construction" + this);
}
/**
* Returns the value stored in the head of this ConsList
*/
public E value() {
return val;
}
/**
* Returns the tail of this ConsList. Returns null if this is NIL
*/
public ConsList<E> tail() {
return tail;
}
/**
* Returns true if this is NIL - the trailing element in a consList.
* A Nil element has no tail and no value
*/
public boolean isNil() {
return tail() == null && val == null;
}
/**
* Returns true if this is the last element in a list.
* Returns true for NIL elements, and the last real element before a NIL element
* Used to stop iteration before it reaches the NIL terminator
*/
public boolean isLast() {
return isNil() || tail().tail() == null && tail().val == null;
}
/**
* Returns a new ConsList that consists of {#code head} prepended
* onto this ConsList
*/
public ConsList<E> cons(E head) {
return new ConsList<E>(head, this, size + 1);
}
/**
* Returns a new ConsList that consists of this full list, reversed.
*/
public ConsList<E> reverse() {
ConsList<E> reversed = new ConsList<E>();
ConsList<E> ptr = this;
while (!ptr.isNil()) {
reversed = reversed.cons(ptr.val);
ptr = ptr.tail;
}
return reversed;
}
/**
* Returns a string representation of a ConsList
*/
#Override
public String toString() {
String s = "(";
ConsList<E> current = this;
while (current != null) {
if (current.val == null && current.tail() == null) {
if (current == this) s += NIL_STRING + ",";
} else {
s += current.val + ",";
}
current = current.tail();
}
return s.substring(0, s.length() - 1) + ")";
}
/**
* Returns true if this equals {#code o}.
* Two ConsLists are equal if they are the same length and every value they
* at each index are equal.
*/
#Override
public boolean equals(Object o) {
if (!(o instanceof ConsList<?>) || o == null) return false;
ConsList<?> lst = (ConsList<?>) o;
return size == lst.size && Objects.equals(val, lst.val) && Objects.equals(tail(), lst.tail());
}
/**
* Returns the size of this list. See {#link common.dataStructures.ConsList#size}
*/
public int size() {
return size;
}
/**
* Returns true iff the size of this list is 0. Equivalently, if this list is NIL
*/
public boolean isEmpty() {
return size == 0;
}
/**
* Returns true iff this list contains the Object o.
* NIL lists do not contain any elements, thus calling contains on a NIL
* list for any input will always return false.
*/
public boolean contains(Object o) {
return !isNil() && (Objects.equals(val, o) || !isLast() && tail().contains(o));
}
/**
* Returns true iff, for all {#code Object o : c}, this.contains(o)
*/
public boolean containsAll(Collection<?> c) {
for (Object o : c) {
if (!contains(o)) return false;
}
return true;
}
/**
* Returns an Iterator over the elements in this ConsList.
* As ConsLists are immutable, the returned iterator does not support removal,
* and cannot throw a ConcurrentModificationException.
* The iterator returned will stop at the last real element in the list,
* *before* the NIL element that terminates all lists. If this method
* is called on the NIL list, the iterator will have no elements to return -
* hasNext() will immediately return false. Thus the iterator behaves as if
* the NIL element does not exist.
*/
#Override
public Iterator<E> iterator() {
return new ConsIterator<E>(this);
}
/**
* Converts this ConsList to an array of Objects.
* The length of the returned array is equal to this.size.
* Therefore for the NIL array, the returned array is of length 0.
*/
public Object[] toArray() {
Object[] arr = new Object[size];
ConsList<E> current = this;
for (int i = 0; i < size; i++, current = current.tail()) {
arr[i] = current.val;
}
return arr;
}
/**
* Converts this ConsList to an array of type T.
* The length of the returned array is equal to Max(this.size, arr.length).
* Therefore for the NIL array, the returned array is of length 0.
* See the List interface for the weird type bullcrap about casting to T[]
*/
#SuppressWarnings("unchecked")
public <T> T[] toArray(T[] arr) {
if (arr.length < size) {
arr = Arrays.copyOf(arr, size);
}
ConsList<E> current = this;
for (int i = 0; i < size; i++, current = current.tail()) {
arr[i] = (T) current.val;
}
return arr;
}
/**
* Returns the {#code index}th element in this list.
*
* #throws IllegalArgumentException - if index < 0 or index >= size - thus throws
* exception if this is called with any index value on the nil list
*/
public E get(int index) {
if (index < 0 || index >= size)
throw new IllegalArgumentException("Can't get element at index " + index + " OOB");
if (index == 0) return val;
return tail().get(index - 1);
}
/**
* Returns the first index of {#code o} in this List, or -1 if it does not occur
*/
public int indexOf(Object o) {
return indexOf(o, 0);
}
/**
* Helper method for the indexOf function - keeps track of how many recursive
* calls have been made thus far to this function to return the correct value
* if {#code o} is found.
*/
private int indexOf(Object o, int x) {
if (Objects.equals(val, o)) return x;
else if (isLast()) return -1;
return tail().indexOf(o, x + 1);
}
/**
* Helper class for iterating over ConsList
* Keeps track of a current list element that will be returned by next() calls.
*
* #param <E>
* #author Mshnik
*/
public static class ConsIterator<E> implements Iterator<E> {
private ConsList<E> current; //next element to return when next() is called
/**
* Creates a new ConsIterator, starting at first
*/
public ConsIterator(ConsList<E> first) {
current = first;
}
/**
* Returns true iff there is another element to iterate over.
* Specifically, returns {#code !current.isNil()}
*/
#Override
public boolean hasNext() {
return !current.isNil();
}
/**
* Returns the next value in this iteration, and moves current
* forward one element.
*/
#Override
public E next() {
E val = current.val;
current = current.tail();
return val;
}
}
}
This all works for type E and covartiants thereof. If I have a ConsList<Animal>, and I call cons(new Dog()), it will give me a ConsList<Animal>, as desired.
However, I've tried every what I can think of to define a contravariant cons method. My best guess looks roughly like this:
public <X super E> ConsList<X> cons(X head) {
return new ConsList(head, this, size+1);
}
Which I would hope would allow me to create a ConsList<String>, cons on new Object and receive a ConsList<Object>.
But this approach doesn't compile, nor does any other attempt I've made. I understand why mutable data structures (i.e. ArrayList) do not support covariance or contravariance, but is there any syntactically valid way to define generic contravariance in Java, even for immutable structures? If so, what is it, and if not, why?
Remark: This is not a complete answer, but it gives an idea how to solve it by pushing some checks to runtime and adding the class-information.
The other question about 'why', i can't answer.
You need to pass an object and the class of the object. Your compiler will here throw an exception if the class is not super E. Although the check if head is really an instance of clazz needs to be done manually.
public <T> ConsList<T> cons(final T head, final Class<? super E> clazz) {
if (clazz.isInstance(head) && head.getClass().equals(clazz)) {
return new ConsList(head, this, this.size + 1);
} else {
throw new IllegalArgumentException("T is not instance of class");
}
}
It is not size as you need to pass the class. But at least you can call it like:
list.cons(headElement, headElement.getClass());
I've written my own implementations of a Stack and a Queue, but I've made them work specifically for integers. I am well aware of the Java implementations, java.util.Stack and java.util.Queue, but I'm doing this as a learning experience... just want to learn something new. How would I make these generic implementations such that I can store any object in my Stack/Queue, not just integers?
Below is the code, but I also welcome all critique and suggestions on improvements. I would like to know what I've done well and what I haven't done well.
STACK NODE IMPLEMENTATION
public class StackNode {
public Integer value;
public StackNode() {
this.value = null;
}
public StackNode(StackNode node) {
this.value = node.value;
}
public StackNode(Integer data) {
this.value = data;
}
}
STACK IMPLEMENTATION
/**
* Stack Data Structure.
*
* A Stack is a last in, first out (LIFO) data structure. A Stack can have any abstract data type as an element, but is
* characterized by two fundamental operations: push() and pop(). The push() operation adds an element to the top of the Stack,
* hiding any elements already on the Stack, or initializing the Stack if it is empty. The pop() operation removes an element
* from the top of the Stack, and returns this element's value to the caller. Elements are removed from the Stack in the reverse
* order to the order of their addition to the Stack; therefore, lower elements are those that have been on the Stack the
* longest, thus, the first element added to the Stack will be the last one to be removed.
*
* #author Hristo
*/
public class Stack {
private int size;
private int capacity;
private int topNodeIndex;
private Object[] theStack;
/**
* Default Constructor. Initalizes this Stack with initial size = 0 and capacity = 1.
*/
public Stack() {
this.size = 0;
this.capacity = 1;
this.topNodeIndex = -1;
this.theStack = new Object[capacity];
}
/**
* Constructor. Initializes a Stack to have the given capacity.
*
* #param capacity - the capacity of the Stack-to-be
*/
public Stack(int capacity) {
this.size = 0;
this.capacity = capacity;
this.topNodeIndex = -1;
this.theStack = new Object[capacity];
}
/**
* Returns the size of this Stack, i.e., how many elements are in this Stack.
*
* #return int - the size of this Stack
*/
public int size() {
return this.size;
}
/**
* Returns the capacity of this Stack, i.e., the maximum number of elements this Stack can hold.
*
* #return int - the capacity of this Stack
*/
public int capacity() {
return this.capacity;
}
/**
* Returns whether or not this Stack is empty, i.e., size == 0.
*
* #return boolean - true if this Stack is empty, false otherwise
*/
public boolean isEmpty() {
return ((this.topNodeIndex == -1) && (this.size == 0)) ? true : false;
}
/**
* Returns whether or not this Stack is full, i.e., size == capacity.
*
* #return boolean - true if this Stack is full, false otherwise
*/
public boolean isFull() {
return (this.size == this.capacity) ? true : false;
}
/**
* Pushes the given value onto the top of this Stack.
*
* #param value - the data to push
*/
public void push(Integer value) {
if (value == null) {
return;
} else {
if (isFull()) {
resize();
}
insert(value);
return;
}
}
/**
* Removes the top element of this Stack and returns the corresponding value.
*
* #return Integer - the value of the top element of this Stack
*/
public Integer pop() {
if (isEmpty()) {
return null;
} else {
return remove();
}
}
/**
* Returns the top element of this Stack without removing it.
*
* #return Integer - the top element of this Stack
*/
public Integer peek() {
return (isEmpty()) ? null : (((StackNode) theStack[this.topNodeIndex]).value);
}
/**
* Inserts the given value onto this Stack.
*
* #param value - the value to insert
*/
private void insert(Integer value) {
theStack[this.topNodeIndex + 1] = new StackNode(value);
this.topNodeIndex++;
this.size++;
return;
}
/**
* Removes the top element of this Stack and returns the corresponding value.
*/
private Integer remove() {
StackNode topNode = (StackNode) theStack[this.topNodeIndex];
theStack[this.topNodeIndex] = null;
this.topNodeIndex--;
this.size--;
return topNode.value;
}
/**
* Creates an array with double the size of the original and copies over the contents from the original.
*/
private void resize() {
Object[] doubleStack = new Object[this.capacity * 2];
for (int index = 0; index < this.size; index++) {
doubleStack[index] = theStack[index];
}
theStack = doubleStack;
capacity *= 2;
return;
}
}
QUEUE NODE IMPLEMENTATION
public class QueueNode {
public Integer value;
public QueueNode() {
this.value = null;
}
public QueueNode(QueueNode node) {
this.value = node.value;
}
public QueueNode(Integer data) {
this.value = data;
}
}
QUEUE IMPLEMENTATION
/**
* Queue Data Structure.
*
* A Queue is a first in, first out (FIFO) data structure. A Queue can have any abstract data type as an element, but is
* characterized by two fundamental operations: enqueue() and dequeue(). The enqueue() operation adds an element to the front of
* the Queue, hiding any elements already in the Queue, or initializing the Queue if it is empty. The dequeue() operation
* removes an element from the front of the Queue, and returns this element's value to the caller. Elements are removed from the
* Queue in the same order to the order of their addition to the Queue; therefore, the first element added to the Queue will be
* the first one to be removed.
*
* #author Hristo
*/
public class Queue {
private int size;
private int capacity;
private int theEndIndex;
private int theFrontIndex;
private Object[] theQueue;
/**
* Default Constructor. Initalizes this Queue with initial size = 0 and capacity = 1.
*/
public Queue() {
this.size = 0;
this.capacity = 1;
this.theEndIndex = -1;
this.theFrontIndex = -1;
this.theQueue = new Object[this.capacity];
}
/**
* Constructor. Initializes a Queue to have the given capacity.
*
* #param capacity - the capacity of the Queue-to-be
*/
public Queue(int capacity) {
this.size = 0;
this.capacity = capacity;
this.theEndIndex = -1;
this.theFrontIndex = -1;
this.theQueue = new Object[capacity];
}
/**
* Returns the size of this Queue, i.e., how many elements are in this Queue.
*
* #return int - the size of this Queue
*/
public int size() {
return this.size;
}
/**
* Returns the capacity of this Queue, i.e., the maximum number of elements this Queue can hold.
*
* #return int - the capacity of this Queue
*/
public int capacity() {
return this.capacity;
}
/**
* Returns whether or not this Queue is empty, i.e., size == 0.
*
* #return boolean - true if this Queue is empty, false otherwise
*/
public boolean isEmpty() {
return ((this.theEndIndex == this.theFrontIndex) && (this.size == 0)) ? true : false;
}
/**
* Returns whether or not this Queue is full, i.e., size == capacity.
*
* #return boolean - true if this Queue is full, false otherwise
*/
public boolean isFull() {
return (this.size == this.capacity && this.theEndIndex == this.theFrontIndex) ? true : false;
}
/**
* Inserts the given value onto the end of this Queue.
*
* #param value - the data to insert
*/
public void enqueue(Integer value) {
if (value == null) {
return;
} else {
if (isEmpty()) {
this.theEndIndex = 0;
this.theFrontIndex = 0;
}
if (isFull()) {
resize();
}
insert(value);
return;
}
}
/**
* Removes the front element in this Queue and returns it.
*
* #return Integer - the front element in this Queue
*/
public Integer dequeue() {
if (isEmpty()) {
return null;
} else {
return remove();
}
}
/**
* Returns the front element of this Queue without removing it.
*
* #return Integer - the front element of this Queue
*/
public Integer peek() {
return (isEmpty()) ? null : (((QueueNode) theQueue[this.theFrontIndex]).value);
}
/**
* Inserts the given value into this Queue.
*
* #param value - the value to insert
*/
private void insert(Integer value) {
this.theQueue[this.theEndIndex] = new QueueNode(value);
/*
* 'theEndIndex' pointer indicates where to insert new QueueNodes in 'theQueue' array. If incrementing this pointer goes
* beyond the size of 'theQueue' array, then pointer needs to wrap around to the beggining of 'theQueue' array.
*/
this.theEndIndex++;
if (this.theEndIndex >= this.theQueue.length) {
this.theEndIndex = 0; // wrap around
}
this.size++;
return;
}
/**
* Removes the front element in this Queue and returns the corresponding value.
*/
private Integer remove() {
QueueNode node = (QueueNode) this.theQueue[this.theFrontIndex];
theQueue[this.theFrontIndex] = null;
/*
* 'theFrontIndex' pointer indicates where to remove QueueNodes from 'theQueue' array. If incrementing this pointer goes
* beyond the size of 'theQueue' array, then pointer needs to wrap around to the beggining of 'theQueue' array.
*/
this.theFrontIndex++;
if (this.theFrontIndex >= this.theQueue.length) {
this.theFrontIndex = 0; // wrap around
}
this.size--;
return node.value;
}
/**
* Creates an array with double the size of the original and copies over the contents from the original.
*/
private void resize() {
Object[] doubleQueue = new Object[this.capacity * 2];
int count = 0;
int iter = this.theFrontIndex;
while (count < this.size) {
doubleQueue[count] = (QueueNode) theQueue[iter];
iter++;
count++;
if (iter >= this.size && this.size > 1) {
iter = 0;
}
}
this.theQueue = doubleQueue;
this.capacity *= 2;
this.theEndIndex = this.size;
this.theFrontIndex = 0;
return;
}
}
Like this (you add the rest):
public class StackNode<T>
{
public T value;
}
public class Stack<T>
{
private int size;
private int capacity;
private int topNodeIndex;
private StackNode<T>[] theStack;
}
The placeholder T describes the type of value help by the node class. So you can create a Stack<Double> or a Stack<Process> or any other type that you wish.