Linked List Implementation with Interface - java

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;
}

Related

Fibonacci Heap Extract Min Implementation Not Working

I am implementing Fibonacci Heap to improve on my Dijkstra's shortest path algorithm. My insert method works fine, and the next one I needed to do is extract-min. I am following CLRS. Please note some attributes mentioned in the book aren't in my implementation yet, as they are not needed for the functions so far, but I will add them later.
private static class FibonacciHeap {
/**
* Implementation of the node used in
* fibonacci heap. The nodes are stored
* as a circular doubly-linked list, making
* delete and insert operations easy, as
* well as being able to iterate through
* without being forced to keep track of the
* head
*/
private class Node {
/**
* The vertex this node is storing
*/
Vertex val;
/**
* Key used to know the order of vertices
*/
int key;
/**
* The left and right sibling in the list
*/
Node left, right;
/**
* Pointer to one of the child's
*/
Node child;
/**
* The amount of children this node has
*/
int degree;
/**
* Constructs a node with a value and key
*
* #param val the value of this node
* #param key the key of this node
*/
public Node(Vertex val, int key) {
this.val = val;
this.key = key;
}
/**
* Inserts a new node into this node's list.
* Inserts it to the left of this node, while
* maintaining the fact that it's circular
*
* #param newNode The new node to be inserted
*/
public void insert(Node newNode) {
newNode.left = left;
left.right = newNode;
newNode.right = this;
left = newNode;
if(newNode.key < min.key) {
min = newNode;
}
size++;
}
/**
* Removes this node from it's list
*/
public void remove() {
right.left = left;
left.right = right;
}
/**
* Inserts a new child into this nodes
* child list
*
* #param child The new node to be added as a child
*/
public void link(Node child) {
child.remove();
if(this.child == null) {
this.child = child;
} else {
this.child.insert(child);
}
degree ++;
}
/**
* Used for debugging. Will be removed after
* all operations work fine
*
* #return A string representation of this node
*/
#Override
public String toString() {
Node dummy = right;
StringBuilder sb = new StringBuilder();
sb.append(key).append(" -> (");
sb.append(dummy.child);
sb.append(") ");
while(dummy != this) {
sb.append(dummy.key).append(" -> (");
sb.append(dummy.child);
sb.append(") ");
dummy = dummy.right;
}
return sb.toString();
}
}
/**
* Pointer to the node with the smallest key
*/
private Node min;
/**
* Stores the number of nodes in the heap
*/
private int size;
/**
* Creates an empty Fibonacci Heap
*/
public FibonacciHeap() { }
/**
* Gets and returns the key with the
* smallest value
*
* #return the key with the smallest value
*/
public int getMin() {
if(min == null) {
throw new NoSuchElementException("Empty Fibonacci Heap");
}
return min.key;
}
/**
* Inserts a vertex along with a key. The
* key is the one used to measure whether
* this vertex is lesser than another
*
* #param vertex vertex to be added
* #param key key of the vertex
*/
public void insert(Vertex vertex, int key) {
if(min == null) {
min = new Node(vertex, key);
min.left = min;
min.right = min;
size = 1;
} else {
min.insert(new Node(vertex, key));
}
}
/**
* Removes the node with the smallest key from
* the heap, and updates the minimum node if needed
*
* #return The node with the smallest key prior to this method call
*/
public Vertex extractMin() {
if(isEmpty()) {
throw new NoSuchElementException("Empty Fibonacci Heap");
}
Vertex toReturn;
if(min == null) {
toReturn = null;
} else {
toReturn = min.val;
if(min.right == min) {
min = null;
} else {
min.remove();
min = min.right;
consolidate();
}
}
return toReturn;
}
/**
* Consolidates the heap. Consolidation is the process
* making every node in the root list have it's own
* unique degree. That is, every node in the top most
* layer has a unique amount of children
*/
private void consolidate() {
Node[] degrees = new Node[size];
degrees[min.degree] = min;
Node tempMin, dummy = (tempMin = min).right;
while(dummy != tempMin) {
if(dummy.key < min.key) {
min = dummy;
}
while(degrees[dummy.degree] != null) {
Node other = degrees[dummy.degree];
if(other.key < dummy.key) {
Node temp = dummy;
dummy = other;
other = temp;
}
dummy.link(other);
degrees[dummy.degree - 1] = null;
}
degrees[dummy.degree] = dummy;
}
}
/**
* Returns true if and only if the
* heap is empty
*
* #return if the heap is empty
*/
public boolean isEmpty() {
return min == null;
}
/**
* A string representation of this
* heap. Format of string is:
* node1 -> (node1.child.toString()) node2 -> (node2.child.toString()) ... noden -> (noden.child.toString())
* The string representation of the
* heap is the string representation of
* the minimum node
*
* #return A string representation of this heap
*/
#Override
public String toString() {
return min.toString();
}
}
This is the stack trace that it gives:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10
at GraphTheory.ShortestPathAlgorithms.DijkstraShortestPath$FibonacciHeap.consolidate(DijkstraShortestPath.java:362)
at GraphTheory.ShortestPathAlgorithms.DijkstraShortestPath$FibonacciHeap.extractMin(DijkstraShortestPath.java:338)
at GraphTheory.ShortestPathAlgorithms.DijkstraShortestPath.main(DijkstraShortestPath.java:104)
The main error is given in the conditional statement of the inner while loop in the consolidate function. I also commented the line in the code. What is going wrong? My main testing method insert 10 random numbers from 1 - 10, and then extracts the minimum until it's empty. The error occurs the first time extract-min is called.
public static void main(String[] args) {
FibonacciHeap f = new FibonacciHeap();
StringBuilder sb = new StringBuilder();
for(int i = 0; i < 10; i ++) {
f.insert(new Vertex(i), (int) (Math.random() * 10));
}
while(!f.isEmpty()) {
System.out.println(f.extractMin());
}
}
Can't pinpoint the exact bug. But, I can tell you from experience that you should not find the minimum while consolidating. You consolidate and then you find the new minimum. You might get into trouble when you have multiple nodes with the same key and the one pointed to by min doesn't end up in the root list.
Also, while testing, don't use a random function. Create an array of arbitrary numbers and insert elements from the array into the heap.
I also don't understand how your implementation handles there being only one heap ordered tree in the Fib heap. What happens when you do an extract-min then?
You can find my Python implementation here if you need it.

Linked List Stack/Queue implementation emptying for no apparent reason?

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.

Implementing an Iterator to a Doubly Linked List

I have been having trouble trying to figure out how to add an iterator to this, I am really confused how to start here is the code. I imported the Iterator but I have no idea where I would begin to add it in here
public class DoublyLinkedList<E> implements Iterator <E> {
/**
* Node of a doubly linked list, which stores a reference to its
* element and to both the previous and next node in the list.
*/
private static class Node<E> {
/** The element stored at this node */
private E element; // reference to the element stored at this node
/** A reference to the preceding node in the list */
private Node<E> prev; // reference to the previous node in the list
/** A reference to the subsequent node in the list */
private Node<E> next; // reference to the subsequent node in the list
/**
* Creates a node with the given element and next node.
*
* #param e the element to be stored
* #param p reference to a node that should precede the new node
* #param n reference to a node that should follow the new node
*/
public Node(E e, Node<E> p, Node<E> n) {
element = e;
prev = p;
next = n;
}
// public accessor methods
/**
* Returns the element stored at the node.
* #return the element stored at the node
*/
public E getElement() {
return element;
}
/**
* Returns the node that precedes this one (or null if no such node).
* #return the preceding node
*/
public Node<E> getPrev() {
return prev;
}
/**
* Returns the node that follows this one (or null if no such node).
* #return the following node
*/
public Node<E> getNext() {
return next;
}
// Update methods
/**
* Sets the node's previous reference to point to Node n.
* #param p the node that should precede this one
*/
public void setPrev(Node<E> p) {
prev = p;
}
/**
* Sets the node's next reference to point to Node n.
* #param n the node that should follow this one
*/
public void setNext(Node<E> n) {
next = n;
}
}
// instance variables of the DoublyLinkedList
/** Sentinel node at the beginning of the list */
private Node<E> header; // header sentinel
/** Sentinel node at the end of the list */
private Node<E> trailer; // trailer sentinel
/** Number of elements in the list (not including sentinels) */
private int size = 0; // number of elements in the list
/** Constructs a new empty list. */
public DoublyLinkedList() {
header = new Node<>(null, null, null); // create header
trailer = new Node<>(null, header, null); // trailer is preceded by header
header.setNext(trailer); // header is followed by trailer
}
// public accessor methods
/**
* Returns the number of elements in the linked list.
* #return number of elements in the linked list
*/
public int size() {
return size;
}
/**
* Tests whether the linked list is empty.
* #return true if the linked list is empty, false otherwise
*/
public boolean isEmpty() {
return size == 0;
}
/**
* Returns (but does not remove) the first element of the list.
* #return element at the front of the list (or null if empty)
*/
public E first() {
if (isEmpty()) return null;
return header.getNext().getElement(); // first element is beyond header
}
/**
* Returns (but does not remove) the last element of the list.
* #return element at the end of the list (or null if empty)
*/
public E last() {
if (isEmpty()) return null;
return trailer.getPrev().getElement(); // last element is before trailer
}
// public update methods
/**
* Adds an element to the front of the list.
* #param e the new element to add
*/
public void addFirst(E e) {
addBetween(e, header, header.getNext()); // place just after the header
}
/**
* Adds an element to the end of the list.
* #param e the new element to add
*/
public void addLast(E e) {
addBetween(e, trailer.getPrev(), trailer); // place just before the trailer
}
/**
* Removes and returns the first element of the list.
* #return the removed element (or null if empty)
*/
public E removeFirst() {
if (isEmpty()) return null; // nothing to remove
return remove(header.getNext()); // first element is beyond header
}
/**
* Removes and returns the last element of the list.
* #return the removed element (or null if empty)
*/
public E removeLast() {
if (isEmpty()) return null; // nothing to remove
return remove(trailer.getPrev()); // last element is before trailer
}
// private update methods
/**
* Adds an element to the linked list in between the given nodes.
* The given predecessor and successor should be neighboring each
* other prior to the call.
*
* #param predecessor node just before the location where the new element is inserted
* #param successor node just after the location where the new element is inserted
*/
private void addBetween(E e, Node<E> predecessor, Node<E> successor) {
// create and link a new node
Node<E> newest = new Node<>(e, predecessor, successor);
predecessor.setNext(newest);
successor.setPrev(newest);
size++;
}
/**
* Removes the given node from the list and returns its element.
* #param node the node to be removed (must not be a sentinel)
*/
private E remove(Node<E> node) {
Node<E> predecessor = node.getPrev();
Node<E> successor = node.getNext();
predecessor.setNext(successor);
successor.setPrev(predecessor);
size--;
return node.getElement();
}
/**
* Produces a string representation of the contents of the list.
* This exists for debugging purposes only.
*/
public String toString() {
StringBuilder sb = new StringBuilder("(");
Node<E> walk = header.getNext();
while (walk != trailer) {
sb.append(walk.getElement());
walk = walk.getNext();
if (walk != trailer)
sb.append(", ");
}
sb.append(")");
return sb.toString();
}
#Override
public boolean hasNext() {
// TODO Auto-generated method stub
return false;
}
#Override
public E next() {
// TODO Auto-generated method stub
return null;
}
} //----------- end of DoublyLinkedList class -----------
First, your List should not implement the Iterator interface. Iterator is capable to traverse only once. Usually lists implement Iterable interface and have iterator() method which can create a new iterator for this list. There are several similar questions answered already. Check this for example.
You do not now how to implement next() and hasNext() methods?
You can store a "current" node element in a field (initialized by first()), and in hasNext() method compare it with last(). In next() method you should assign current node the getNext() of it an return the node.

Java- Error concerning Generics

I have a class & and inner class that work together to make a linked list. The data held by the nodes, is Generic, and I somewhere along the line of my code I screwed up involving generics but I don't know where. I get 5 errors, the first one says "type LinkedList does not take parameters" which i think is weird because LinkedList is just an interface that i'm implementing. The rest of them are phrased "Object cannot be converted to E". I marked where they're occurring. I figured my assignment was right I don't know what's wrong. If you'd like me to post the interface LinkedList let me know.
public class SinglyLinkedList<E> implements LinkedList<E> {
private Node head;
private Node tail;
private int size;
public SinglyLinkedList(){
this.head = null;
this.tail = null;
this.size = 0;
}
public E get(int index) {
//Hold the data of the cur node
//and keep iterating until you hit the
//right index
int hit = 0;
Node pos = this.head;
E found = this.head.data;//////ERROR HERE
while (hit < index) {
pos = pos.next;
found = pos.data;//////ERROR HERE
hit++;
}
return found;
}
public void add (E data) {
Node last = new Node(data, null);
//If the list is empty.
if (this.head == null) {
this.head = last;
}
//Make the cur tail's next the new node
//and set the new node as the new tail.
this.tail.next = last;
this.tail = last;
this.size++;
}
public boolean add(int index, E data) {
//Cannot add if index is not valid
if ((index >= this.size) || (index < 0) ) {
return false;
}
//If index is 0, add at beginning
Node insert = new Node(data, null);
if (index == 0) {
insert.next = this.head;
this.head = insert;
this.size++;
return true;
} else {
//Else, go until you reach desired index then
//Set whatever was at that index to the new Node's
//next value.
int hit = 1;
Node cur = this.head;
while (hit < index) {
cur = cur.next;
hit++;
}
insert.next = cur;
this.size++;
return false;
}
}
public void addAll(Collection<? extends E> c) {
for (E item: c) {
this.add(item);
}
}
public boolean contains(E data) {
int hit = 0;
Node cur = this.head;
Node move;
while (hit < this.size) {
if (data.equals(cur.data)) {
return true;
} else {
move = cur.next;
cur = move;
}
}
return false;
}
public boolean containsAll(Collection<? extends E> c) {
for (E item: c) {
if (!(this.contains(item))) {
return false;
}
}
return true;
}
public boolean remove(E data) {
Node prev = this.head;
Node cur = this.head.next;
int hit = 1;
if (!(this.contains(data))) {
return false;
} else if (data.equals(head.data)) {
this.head = cur;
return true;
this.size--;
}
while (hit < this.size) {
if (data.equals(cur.data)) {
prev.next = cur.next;
return true;
this.size--;
}
hit++;
}
}
public E remove(int index) {
int hit = 1;
E data;
Node prev = this.head;
Node cur = this.head.next;
if (index == 0) {
data = head.data; //////ERROR HERE
this.head = cur;
return data;
this.size--;
} else {
while (hit < this.size) {
if ( hit == index) {
data = cur.data; //////ERROR HERE
prev.next = cur.next;
return data;
this.size--;
} else {
prev = cur;
cur = prev.next;
hit++;
}
}
}
}
public boolean removeAll(Collection<? extends E> c) {
int prevSize = this.size;
for (E item: c) {
remove(item);
}
return (prevSize < this.size);
}
public int size() {
return this.size;
}
public boolean isEmpty() {
return (this.head == null);
}
public void clear() {
this.head = null;
this.tail = null;
size = 0;
}
private class Node<E> {
private E data;
private Node next;
private Node(E data, Node next) {
this.data = data;
this.next = next;
}
}
}
This is the interface class
/**
* The LinkedList interface defines a set of standard operations that are
* typically associated with linked list, such as adding, removing, and checking
* to see if the list contains an item.
*
* Note that while your linked list implementation should make use of a Node
* class, the methods below take in and return instances of the generic type,
* not the nodes themselves.
*
* #author Justin Nieto
* #version 1.1
* #param <E> the type of the elements to store in the linked list
*/
public interface LinkedList<E> {
/**
* Returns the element in the linked list at the specified index.
* Does not change the contents of the list in any way. If the given
* index is negative or greater than the maximum possible index, returns
* null.
*
* #param index of element to be retrieved
* #return the element at the given index or null if index out of bounds
*/
E get(int index);
/**
* Adds the specified piece of data to the end of the linked list.
* This method should execute in O(1) (constant) time. This means that
* you should not iterate over the whole list to add the item to the end
* (we will check for this).
*
* #param data the object to be added to the linked list
*/
void add(E data);
/**
* Adds given piece of data to the linked list at the given index.
* All items that were originally at the index or after the index should
* be shifted down by one. If the index specified is not valid, returns
* false. Otherwise, returns true.
*
* If the index specified is 0 or if it is one larger than the maximum
* current index (ie if index is equal to the size of the linked list),
* then this method should execute in O(1) (constant) time. This means that
* you should not iterate over the entire list to add the element, as it
* is unnecessary to do so.
*
* #param index the index at which to add the item
* #param data the item to be added to te linked list
* #return true if the data could be added at the given index
*/
boolean add(int index, E data);
/**
* Adds each element in the Collection to the end of the linked list.
*
* #param c the collection of items to add to the end of the linked list
*/
void addAll(Collection<? extends E> c);
/**
* Determines whether or not the given piece of data is in the linked list.
*
* #param data the item to check
* #return true if the linked list contains the item, false otherwise
*/
boolean contains(E data);
/**
* Determines whether or not every element of the given Collection is
* in the linked list.
*
* #param c the Collection of elements to check
* #return true if list contains every element in the Collection
*/
boolean containsAll(Collection<? extends E> c);
/**
* Finds the first element of the list equal to the given piece of data
* and removes it from the list. Returns false if the given piece of data
* is not in the list and therefore cannot be removed.
*
* #param data the piece of data to be removed from the list
* #return true if the item was removed, false if list does not contain it
*/
boolean remove(E data);
/**
* Removes and returns the item in the list at the given index.
* All items at indices after the given index are shifted down by one.
*
* #param index the index of the item to remove from the linked list
* #return the removed item
*/
E remove(int index);
/**
* Removes each element in the given collection from the linked list.
*
* #param c the Collection of items to remove
* #return true if each element in the Collection was removed.
*/
boolean removeAll(Collection<? extends E> c);
/**
* Returns the number of elements in the linked list. This method
* should execute in O(1) (constant) time. This means that you should not
* iterate over the entire list to count the number of items, but rather
* you should maintain a size variable that you can just return here.
*
* #return the number of elements in the linked list
*/
int size();
/**
* Returns true if the linked list has no elements.
*
* #return true if the list is empty, false otherwise
*/
boolean isEmpty();
/**
* Removes all elements from the list. After calling this method,
* the isEmpty method should return true.
*/
void clear();
}
Node is an inner class of SinglyLinkedList, so it already shares the type parameter E. Therefore you could make Node a non-generic class.
private class Node {
private E data;
private Node next;
private Node(E data, Node next) {
this.data = data;
this.next = next;
}
}
That removes many of the problems, because before Node was a generic class and you were using Node without a type parameter.
An alternative solution is to make Node a static nested class. This means that an instance of Node does not belong to an instance of SinglyLinkedList. Because of this, a static version of Node would need its own type parameter.
private static class Node<E> {
private E data;
private Node<E> next;
private Node(E data, Node<E> next) {
this.data = data;
this.next = next;
}
}
Notice that in this version, Node is generic, so I had to add <E> after it every time it appeared. If you go with the static approach, you will have to add <E> after every occurrence of Node in the rest of the class. There are lots of these.
Finally, the message "LinkedList does not take parameters" is self-explanatory. Presumably it says interface LinkedList when it should say interface LinkedList<E>.

How would I make these data structure implementations generic, in Java?

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.

Categories