I have made my own implementation of a generic Linked Queue for class, it is pretty much finished, here it is:
public class LinkedQueue<T> implements Queue<T> {
//Using head & tail approach.
private myNode<T> head;
private myNode<T> tail;
private int size;
public LinkedQueue(){
this.head = null;
this.tail = head;
this.size = 0;
}
public myNode<T> getterHead(){ //couldn't bring myself to write "get" instead of "getter"
return this.head;
}
#Override
public int size() {
return this.size; //returns number of nodes
}
#Override
public boolean isEmpty() {
return this.head==null;
}
#Override
public void enqueue(T element) {
if(isEmpty()){
this.head = new myNode<T>(element);
this.tail = head;
size++;
}
else{
this.tail.next = new myNode<T>(element);
this.tail = tail.next;
size++;
}
}
#Override
public T dequeue() {
if(isEmpty())throw new NoSuchElementException("This queue is empty");
T returnObj = this.head.data; //saving the data of the first element(head)
//If there are at least 2 nodes, else.
if(head != tail){
this.head = head.getNext();
size--;
}
else{
this.head = null;
this.tail = head;
this.size = 0;
}
return returnObj;
}
#Override
public T first() {
return this.head.data;
}
#Override
public T last() {
return this.tail.data;
}
/* I absolutely can not get past this NullPointerException that is given every time
* I try to use the iterator. It seems that current.next is always null(doesn't point to head properly?).
* HOWEVER, if you change "curr" for "head", it works. */
#Override
public Iterator<T> iterator() {
return new GenericIterator();
}
private class GenericIterator implements Iterator<T>{
public myNode<T> curr = head;
public boolean hasNext() {
return (head != null && head.next != null);
}
public T next() {
T tmp = head.data; //saving current in a temporary node because we are changing the value of current in the next line
if(hasNext()){
head = head.next;
}
return tmp;
}
}
private class myNode<T> { //parameter type T hiding type T
public T data; //The generic data the nodes contain
public myNode<T> next; //Next node
//Node constructor
public myNode(T nData) {
this.data = nData;
this.next = null;
}
public myNode<T> getNext(){
return this.next;
}
}
}
Here is the part that is giving me trouble:
/* I absolutely can not get past this NullPointerException that is given every time
* I try to use the iterator. It seems that current.next is always null(doesn't point to head properly?).
* HOWEVER, if you change "curr" for "head", it works. */
#Override
public Iterator<T> iterator() {
return new GenericIterator();
}
private class GenericIterator implements Iterator<T>{
public myNode<T> curr = head; //doesn't work with getter either.
//public myNode<T> curr = getterHead();
public boolean hasNext() {
return (curr != null && curr.next != null);
}
public T next() {
T tmp = curr.data; //NPE HERE!
if(hasNext()){
curr = curr.next;
}
return tmp;
}
}
What I have tried is getters/setters and triple-checking every other method(they work). What seems to be the problem is that when I assign curr = head, it seems that the properties from myNode do not come with.
While head.next works fine, curr.next == null, even curr.data == null while head.data works.
I've tried with public properties and printing LinkedQueue.head.next etc, it works fine.
Stacktrace:
Exception in thread "main" java.lang.NullPointerException
at dk222gw_lab4.Queue.LinkedQueue$GenericIterator.next(LinkedQueue.java:101)
at dk222gw_lab4.Queue.LinkedQueueMain.main(LinkedQueueMain.java:17)
Where line 101 & 17 are:
T tmp = curr.data; //node property .data & .next are null.
System.out.println(it.next()); //LinkedQueueMain.java(not included in post), both it.next() and it.hasNext() produce this NPE.
Related
I'm trying to make a generic stack and queue class that uses the generic node class. It has empty(), pop(), peek(), push(), and a search() method. I know there is a built-in Stack class and stack search method but we have to make it by using the Node class.
I am unsure of how to make the search method. The search method is supposed to return the distance from the top of the stack of the occurrence that is nearest the top of the stack. The topmost item is considered to be at distance 1; the next item is at distance 2; etc.
My classes are below:
import java.io.*;
import java.util.*;
public class MyStack<E> implements StackInterface<E>
{
private Node<E> head;
private int nodeCount;
public static void main(String args[]) {
}
public E peek() {
return this.head.getData();
}
public E pop() {
E item;
item = head.getData();
head = head.getNext();
nodeCount--;
return item;
}
public boolean empty() {
if (head==null) {
return true;
} else {
return false;
}
}
public void push(E data) {
Node<E> head = new Node<E>(data);
nodeCount++;
}
public int search(Object o) {
// todo
}
}
public class Node<E>
{
E data;
Node<E> next;
// getters and setters
public Node(E data)
{
this.data = data;
this.next = null;
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> next) {
this.next = next;
}
}
public class MyQueue<E> implements QueueInterface<E>
{
private Node<E> head;
private int nodeCount;
Node<E> rear;
public MyQueue()
{
this.head = this.rear = null;
}
public void add(E item){
Node<E> temp = new Node<E>(item);
if (this.rear == null) {
this.head = this.rear = temp;
return;
}
this.rear.next = temp;
this.rear = temp;
}
public E peek(){
return this.head.getData();
}
public E remove(){
E element = head.getData();
Node<E> temp = this.head;
this.head = this.head.getNext();
nodeCount--;
return element;
}
}
After working on it based off of the first comment I have this:
public int search(Object o){
int count=0;
Node<E> current = new Node<E> (head.getData());
while(current.getData() != o){
current.getNext();
count++;
}
return count;
}
It doesn't have any errors but I cannot tell if it is actually working correctly. Does this seem correct?
It needs the following improvements,
search method should have parameter of type 'E'. So, the signature should look like public int search(E element)
start the count with 1 instead of 0.As you have mentioned topmost item is considered to be at distance 1
initialize current with head, because creating a new node with data value of head(new node(head.getData())) will create an independent node with data same as head node; and the while will run only for the head node as current.getNext() will be null always. Node<E> current = head will create another reference variable pointing to the head.
Instead of != in condition, use if( !current.getData().equals(element.getData())) )
If using your own class as data type, don't forget to override equals method.
Change current.getNext(); to current = current.getNext();
You have problems with other method. Pay attention on top == null. To calculate search() all you need is just iterate over the elements and find position of required value:
public class MyStack<E> {
private Node<E> top;
private int size;
public void push(E val) {
Node<E> node = new Node<>(val);
node.next = top;
top = node;
size++;
}
public E element() {
return top == null ? null : top.val;
}
public E pop() {
if (top == null)
return null;
E val = top.val;
top = top.next;
size--;
return val;
}
public boolean empty() {
return size == 0;
}
public int search(E val) {
int res = 1;
Node<E> node = top;
while (node != null && node.val != val) {
node = node.next;
res++;
}
return node == null ? -1 : res;
}
private static final class Node<E> {
private final E val;
private Node<E> next;
public Node(E val) {
this.val = val;
}
}
}
I assume your MyStack class should be compatible with the Stack class provided by Java as you mention it in your question. This means that your signature public int search(Object o) matches the signature of java.util.Stack#search (apart from synchronised).
To implement the search method using your Node class, we need to traverse the stack and return the index of the first (uppermost) match. First, assign head to a local variable (current). Then you can create a loop where you current.getNext() at the end to get the next element. Stop if the next element is null as we have reached the end of the stack. In the loop, you either count up the index or return this index when the current element's data matches the argument o.
The evaluation needs to be able to deal with null values for your argument o. Therefore, you need to check for null first and adjust your logic accordingly. When o is null, do a null-check against current.getData(). If o is not null, check if current.getData() is equal to o with equals().
Here is a working example: (compatible with java.util.Stack#search)
public int search(Object o) {
int index = 1;
Node<E> current = head;
while (current != null) {
if (o == null) {
if (current.getData() == null) {
return index;
}
} else {
if (o.equals(current.getData())) {
return index;
}
}
current = current.getNext();
index++;
}
return -1; // nothing found
}
To test this, you can write a simple unit test with JUnit like this:
#Test
public void testMyStackSearch() {
// initialize
final MyStack<String> stack = new MyStack<>();
stack.push("e5");
stack.push("e4");
stack.push(null);
stack.push("e2");
stack.push("e1");
// test (explicitly creating a new String instance)
assertEquals(5, stack.search(new String("e5")));
assertEquals(3, stack.search(null));
assertEquals(2, stack.search(new String("e2")));
assertEquals(1, stack.search(new String("e1")));
assertEquals(-1, stack.search("X"));
}
Since you have already a reference implementation, you can replace MyStack with Stack (java.util.Stack) and see if your asserts are correct. If this runs successfully, change it back to MyStack and see if your implementation is correct.
Note: I do not recommend to actually use the Stack implementation in Java. Here, it just serves as a reference implementation for the java.util.Stack#search method. The Deque interface and its implementations offer a more complete and consistent set of LIFO stack operations, which should be used in preference to Stack.
I am trying to print the first and last elements in a deque using a toString method however I'm not entirely sure if I am overwriting the toString method correctly.
As far as I can tell, the methods all seem to behave correctly but I have no way of being able to tell as I am unable to see any readable output.
I am aware that there is already a deque interface, however this is part of an exercise in using generics in Java.
This piece of code should create a deque, be able to add values to the front of the deque, remove values from the front, add values to the rear and remove values from the rear.
Here's the class in question:
import java.util.Iterator;
import java.util.NoSuchElementException;
class Deque<T> implements Iterable<T> {
private class Node<T> {
public Node<T> left, right;
private final T item;
public Node(T item) {
if (item == null) {
throw new NullPointerException();
}
this.item = item;
}
public void connectRight(Node<T> other) {
this.right = other;
other.left = this;
}
}
private class DequeIterator implements Iterator<T> {
private Node<T> curr = head;
public boolean hasNext() {
return curr != null;
}
public void remove() {
throw new UnsupportedOperationException();
}
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
T item = curr.item;
curr = curr.right;
return item;
}
}
private Node<T> head, tail;
private int size;
public Iterator<T> iterator() {
return new DequeIterator();
}
public Deque() {
}
public int size() {
return size;
}
public boolean isEmpty() {
return size() == 0;
}
public void checkInvariants() {
assert size >= 0;
assert size > 0 || (head == null && tail == null);
assert (head == null && tail == null) || (head != null && tail != null);
}
public void addFirst(T item) {
Node<T> prevHead = head;
Node<T> newHead = new Node<T>(item);
if (prevHead != null) {
newHead.connectRight(prevHead);
} else {
tail = newHead;
}
head = newHead;
size++;
checkInvariants();
}
public void addLast(T item) {
Node<T> newTail = new Node<T>(item);
Node<T> prevTail = tail;
if (prevTail != null) {
prevTail.connectRight(newTail);
} else {
head = newTail;
}
tail = newTail;
size++;
checkInvariants();
}
public T removeFirst() {
if (isEmpty()) {
throw new java.util.NoSuchElementException();
}
size--;
Node<T> prevHead = head;
head = prevHead.right;
prevHead.right = null;
if (head != null) {
head.left = null;
}
checkInvariants();
return prevHead.item;
}
public T removeLast() {
if (isEmpty()) {
throw new java.util.NoSuchElementException();
}
size--;
Node<T> prevTail = tail;
tail = prevTail.left;
prevTail.left = null;
if (tail != null) tail.right = null;
checkInvariants();
return prevTail.item;
}
#Override
public String toString() {
Node<T> currTail = tail;
Node<T> currHead = head;
head = currHead.right;
tail = currTail.left;
StringBuilder builder = new StringBuilder();
while (currHead != null && currTail != null) {
builder.append(currHead.item + "\n");
}
return builder.toString();
}
public static void main(String[] args) {
Deque<Double> d = new Deque<Double>();
d.addFirst(1.0);
System.out.println(d);
d.addLast(1.0);
//d.removeFirst();
//d.removeLast();
System.out.println(d.toString());
}
}
First of all, you're setting the instance variables head and tail to their respective neighbours, which is definitely not what you're out to do. This leaves your queue in an inconsistent state, where the second element is the head, but it still has a left neighbour, the original head. Same thing for the tail. Generally the toString method shouldn't have side effects.
Neither currTail nor currHead ever change in your while-loop, so your condition currHead != null && currTail != null will always be true if the deque is non-empty. You'd have to set those variables in the loop, however, you don't need to iterate from both ends at once. Iterating from the start will be enough. And then, you can use a for loop, like this:
#Override
public String toString() {
final StringJoiner stringJoiner = new StringJoiner("\n");
for (Node<T> node = head; node != null; node = node.right) {
stringJoiner.add(node.item.toString());
}
return stringJoiner.toString();
}
This sets the variable node to it's right neighbour after every iteration, and if the deque is empty, node will be null from the get-go and the loop will not be entered as is expected.
This is just the more concise (In my opinion) version of this:
#Override
public String toString() {
final StringJoiner stringJoiner = new StringJoiner("\n");
Node<?> node = head;
while (node != null) {
stringJoiner.add(node.item.toString());
node = node.right;
}
return stringJoiner.toString();
}
which is basically your attempt, just fixed.
Not that I've used a StringJoiner instead of a StringBuilder, as it allows you to set a delimeter that is used between each String, which is exactly what you're doing.
I have created a queue implementation using a single connection list.In this code I am using 2 pointers (first,last) to define the start and the end of my queue. My code is :
import java.io.PrintStream;
import java.util.*
/**
* #author Justin Bieber
*/
public class StringQueueImpl<T> implements StringQueue {
private int total; // number of elements on queue
private Node head; // beginning of queue
private Node tail; // end of queue
private class Node {
T ele;
Node next;
Node(T ele) {
this.ele = ele;
next = null; }
}
/**
* Creates an empty queue.
*/
public StringQueueImpl() {
first = null;
last = null;
total = 0;
}
boolean isEmpty() {
return (head == null);
}
public <T> void put(T ele) {
Node t = tail;
tail = new Node(ele);
if (isEmpty()) head = tail;
else t.next = tail;
total++;
}
public T get() {
if (isEmpty()) throw new NoSuchElementException();
T v = head.ele;
Node t = head.next;
head = t;
return v;
total--;
}
public T peek() {
if (isEmpty()) throw new NoSuchElementException();
return head.ele;
}
Node node = head;
public void printQueue(PrintStream stream){
while(node != null){
stream.println(node.ele);
stream.flush();
node = node.next;
}
}
public int size(){
return total;
}
}
My question is how can I create a queue implementation using a circular list. (Instead of 2 pointers for the start and the end I would like to use only one pointer wich will be used for both the start and the end of the queue).
Any help is apreciated . Thank you
My project should implement two classes. A basic linked list and a sorted linked list. Everything seems to be working fine except for some reason I can't iterate through the sorted linked list. The class structure is as follows:
public class BasicLinkedList<T> implements Iterable<T> {
public int size;
private class Node {
private T data;
private Node next;
private Node(T data) {
this.data = data;
next = null;
}
}
private Node head;
private Node tail;
public BasicLinkedList() {
head = tail = null;
}
//Add, remove method
public Iterator<T> iterator() {
return new Iterator<T>() {
Node current = head;
#Override
public boolean hasNext() {
return current != null;
}
#Override
public T next() {
if(hasNext()){
T data = current.data;
current = current.next;
return data;
}
return null;
}
#Override
public void remove(){
throw new UnsupportedOperationException("Remove not implemented.");
}
};
Now when I test this class it works just fine. The iterator works and I can test it all. The problem is in the sorted linked list class which extends this one. Here's its implementation and a comparator class that I'm using in the constructor:
public class SortedLinkedList<T> extends BasicLinkedList<T>{
private class Node{
private T data;
private Node next;
private Node(T data){
this.data = data;
next = null;
}
}
private Node head;
private Node tail;
private Comparator<T> comp;
public SortedLinkedList(Comparator<T> comparator){
super();
this.comp = comparator;
}
Here's the comparator class and the test I ran in a separate class:
public class intComparator implements Comparator<Integer>{
#Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}
public static void main(String[] args) {
System.out.println("---------------SortedLinkedList--------------");
SortedLinkedList<Integer> sortedList = new SortedLinkedList<Integer>(new intComparator());
sortedList.add(3);
sortedList.add(5);
sortedList.add(2);
for(int i: sortedList){
System.out.println(i);
}
}
Nothing prints out. I assumed the iterator that was inherited would help me traverse this no problem and clearly its legal because the for-each loop compiles. It's just that nothing gets printed out. I debugged it and all the adding, removing stuff works as expected. It's just that the iterator isn't doing what it's supposed to. Should I create a separate new iterator for this class? But wouldn't that be redundant code since I already inherit it? Help appreciated!
EDIT: Here's the add method for the sorted list
public SortedLinkedList<T> add(T element){
Node n = new Node(element);
Node prev = null, curr = head;
if(head == null){
head = n;
tail = n;
}
//See if the element goes at the very front
else if(comp.compare(n.data, curr.data) <= 0){
n.next = head;
head = n;
}
//See if the element is to be inserted at the very end
else if(comp.compare(n.data, tail.data)>=0){
tail.next = n;
tail = n;
}
//If element is to be inserted in the middle
else{
while(comp.compare(n.data, curr.data) > 0){
prev = curr;
curr = curr.next;
}
prev.next = n;
n.next = curr;
}
size++;
return this;
}
1) SortedLinkedList extends BasicLinkedList but both have
private Node head;
private Node tail
this is wrong. If you want to inherit those field in the sub class, you should mark the variables as protected in the super class and remove them from the subclass.
2) Same goes for private class Node. You are declaring the Node class in both the SortedLinkedList and BasicLinkedList. What you should do is declare it once, (maybe in the super class?) and use the same class in both places. If you do this, the constructor, and the fields should be accessible to both classes. So you will have to change the access modifier (private is what you have now).
I will post below code that works, but I haven't spent any time on the design. Just posting it to demonstrate how you could change the code to make it work. You will have to decide which access modifiers to use and where to put the classes.
import java.util.Comparator;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
System.out.println("---------------SortedLinkedList--------------");
SortedLinkedList<Integer> sortedList = new SortedLinkedList<Integer>(new intComparator());
sortedList.add(3);
sortedList.add(5);
sortedList.add(2);
for (int i : sortedList) {
System.out.println(i);
}
}
}
class BasicLinkedList<T> implements Iterable<T> {
public int size;
class Node {
T data;
Node next;
Node(T data) {
this.data = data;
next = null;
}
}
protected Node head;
protected Node tail;
public BasicLinkedList() {
head = tail = null;
}
// Add, remove method
public Iterator<T> iterator() {
return new Iterator<T>() {
Node current = head;
#Override
public boolean hasNext() {
return current != null;
}
#Override
public T next() {
if (hasNext()) {
T data = current.data;
current = current.next;
return data;
}
return null;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Remove not implemented.");
}
};
}
}
class SortedLinkedList<T> extends BasicLinkedList<T> {
private Comparator<T> comp;
public SortedLinkedList(Comparator<T> comparator) {
super();
this.comp = comparator;
}
public SortedLinkedList<T> add(T element) {
Node n = new Node(element);
Node prev = null, curr = head;
if (head == null) {
head = n;
tail = n;
}
// See if the element goes at the very front
else if (comp.compare(n.data, curr.data) <= 0) {
n.next = head;
head = n;
}
// See if the element is to be inserted at the very end
else if (comp.compare(n.data, tail.data) >= 0) {
tail.next = n;
tail = n;
}
// If element is to be inserted in the middle
else {
while (comp.compare(n.data, curr.data) > 0) {
prev = curr;
curr = curr.next;
}
prev.next = n;
n.next = curr;
}
size++;
return this;
}
}
class intComparator implements Comparator<Integer> {
#Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}
My problem is in the add method. I think I know what I want it to do but I can't figure out what type of loop I should use to look through the list. As you can see I started to make a if else loop but I couldn't figure out what I should use as the counter. I'm pretty sure I have the right logic in dealing with the add but I feel like I'm not quite there yet. I was thinking of using compareTo in some fashion.
import java.util.*;
public class OrderedLinkedList<E extends Comparable<E>>
{
private Node topNode;
private class Node
{
private E data;
private Node nextNode;
public Node(E data)
{
this.data = data;
nextNode = null;
}
}
public OrderedLinkedList()
{
topNode = null;
}
public boolean empty()
{
if(topNode == null)
return true;
return false;
}
public String toString()
{
String myString = "";
Node nextNode = topNode;
while(nextNode != null)
{
myString = topNode + " -> " + nextNode;
nextNode = topNode.nextNode;
}
return myString;
}
public void add(E data)
{
Node myNode = new Node(data);
Node priorNode = topNode;
Node currentNode = topNode;
if(___)
{
priorNode = currentNode;
currentNode = currentNode.nextNode;
}
else
{
priorNode.nextNode = myNode;
myNode.nextNode = currentNode;
}
}
}
Since you don't typically know the length of a linked list until you've walked down it, the usual thing would be to use a while loop (as you've done in your toString() method)
Perhaps using a doubly linked list would be more beneficial. Consider the following alterations to your class:
import java.util.*;
public class OrderedLinkedList<E extends Comparable<E>>
{
private Node head;
private Node tail;
private class Node
{
private E data;
private Node nextNode;
private Node prevNode;
public Node(E data)
{
this.data = data;
nextNode = null;
prevNode = null;
}
public void setNext(Node node)
{
this.nextNode = node;
}
public Node getNext()
{
return this.nextNode;
}
public void setPrev(Node node)
{
this.prevNode = node;
}
public Node getPrev()
{
return this.prevNode;
}
public E getData()
{
return this.data;
}
public int compareTo(Node that) {
if(this.getData() < that.getData())
{
return -1;
}
else if(this.getData() == that.getData()
{
return 0;
}
else
{
return 1;
}
}
}
public OrderedLinkedList()
{
head = new Node(null);
tail = new Node(null);
head.setNext(tail);
tail.setPrev(head);
}
public boolean empty()
{
if(head.getNext() == tail)
{
return true;
}
return false;
}
public void add(E data) {
Node tmp = new Node(data);
if(this.empty()) {
this.addNodeAfterNode(tmp, head);
} else {
Node that = head.getNext();
// this while loop iterates over the list until finding the correct
// spot to add the new node. The correct spot is considered to be
// when tmp's data is >= that's data, or the next node after 'that'
// is tail. In which case the node is added to the end of the list
while((tmp.compareTo(that) == -1) && (that.getNext() != tail)) {
that = that.getNext();
}
this.addNodeAfterNode(tmp, that);
}
}
private void addNodeAfterNode(Node addNode, Node afterNode)
{
addNode.setNext(afterNode.getNext());
afterNode.getNext().setPrev(addNode);
afterNode.setNext(addNode);
addNode.setPrev(afterNode);
}
}