I am trying to learn Generics and Iterators in java and have created following code ->
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Deque<Item> implements Iterable<Item>
{
private int N; // number of elements on list
private Node<Item> pre; // sentinel before first item
private Node<Item> post; // sentinel after last item
/*
* linked list node helper data type
*/
private static class Node<Item>
{
private Item item;
private Node<Item> next;
private Node<Item> prev;
}//class Node<Item> ends
/*
*construct an empty deque
*/
public Deque()
{
pre = new Node<Item>();
post = new Node<Item>();
pre.item = null;
post.item = null;
pre.prev = null;
post.next = null;
pre.next = post;
post.prev = pre;
N = 0;
}//Deque ends
/*
* is the deque empty?
*/
public boolean isEmpty()
{
//if( ((pre.next == post)&&(post.prev == pre)) || ( N == 0 ) ) return true;
if( N == 0 ) return true;
else return false;
}//isEmpty ends
/*
* return the number of items on the deque
*/
public int size()
{
return N;
}//size ends
/*
* insert the item at the front
* This is extension of Queue, so First is the location near Post Node
* pre-> <-post, pre->1<-post, pre->1,2<-post, pre->1,2,3<-post ...
* ^ ^ ^ ^ ^ ^ ^
* | | | | | | |
* initial these all are the effects of addFirst()
* condition
*/
public void addFirst(Item item)
{
//System.out.println("We are outside ListIterator - addFirst");
if( isEmpty() ) //here pre.next == post.prev
{
//System.out.println("We are inside isEmpty");
Node<Item> NewNode = new Node<Item>();
NewNode.item = item;
NewNode.next = post;
post.prev = NewNode;
NewNode.prev = pre;
pre.next = NewNode;
N++;
//System.out.println(NewNode.item);
}//if ends
else //here pre.next->1.prev & X.next->post
{
//System.out.println("We are inside !isEmpty");
Node<Item> NewNode = new Node<Item>();
Node<Item> last = post.prev;
NewNode.item = item;
NewNode.next = post;
post.prev = NewNode;
NewNode.prev = last;
last.next = NewNode;
N++;
//System.out.println(NewNode.item);
}//else ends
}//addFirst ends
/*
*insert the item at the end
* This is extension of Queue, so First is the location near Post Node
* pre-> <-post, pre->1<-post, pre->2,1<-post, pre->3,2,1<-post ...
* ^ ^ ^ ^ ^ ^ ^
* | | | | | | |
* initial these all are the effects of addLast()
* condition
*/
public void addLast(Item item)
{
//System.out.println("We are outside ListIterator - addLast");
if( isEmpty() ) //here pre.next == post.prev
{
//System.out.println("We are inside isEmpty");
Node<Item> NewNode = new Node<Item>();
NewNode.item = item;
NewNode.next = post;
post.prev = NewNode;
NewNode.prev = pre;
pre.next = NewNode;
N++;
System.out.println(NewNode.item);
}//if ends
else //here pre.next->1.prev & X.next->post
{
//System.out.println("We are inside !isEmpty");
Node<Item> NewNode = new Node<Item>();
Node<Item> last = pre.next;
NewNode.item = item;
NewNode.next = last;
pre.next = NewNode;
NewNode.prev = pre;
last.prev = NewNode;
N++;
System.out.println(NewNode.item);
}//else ends
}//addLast ends
/*
* delete and return the item at the front
* This is extension of Queue, so Last is the location near Pre Node
* pre->1,2,3<-post, pre->1,2<-post, pre->1<-post, pre-> <-post...
* ^ ^ ^ ^ ^ ^ ^
* | | | | | | |
* initial these all are the effects of removeFirst()
* condition
*/
public Item removeFirst()
{
if( isEmpty() ) throw new NoSuchElementException("Queue underflow EXIT" );
else
{
Item item = post.prev.item;
post.prev = post.prev.prev;
N--;
if( isEmpty() )
{
post.prev = pre;
pre.next = post;
N = 0;
}//if ends
return item;
}//else ends
}//removeFirst ends
/*
* delete and return the item at the end
* This is extension of Queue, so Last is the location near Pre Node
* pre->1,2,3<-post, pre->2,3<-post, pre->3<-post, pre-> <-post...
* ^ ^ ^ ^ ^ ^ ^
* | | | | | | |
* initial these all are the effects of removeLast()
* condition
*/
public Item removeLast()
{
if( isEmpty() ) throw new NoSuchElementException("Queue underflow EXIT" );
else
{
Item item = pre.next.item;
pre.next = pre.next.next;
N--;
if( isEmpty() )
{
pre.next = post;
post.prev = pre;
N = 0;
}//if ends
return item;
}//else ends
}//removeLast ends
/*
* return an iterator over items in order from front to end
* Returns an iterator that iterates over the items in this queue in FIFO order.
*/
public Iterator<Item> iterator()
{
return new ClassIterator<Item>(pre);
}//Iterator<Item> iterator() ends
// an iterator, doesn't implement remove() since it's optional
private static class ClassIterator<Item> implements Iterator<Item>
{
private Node<Item> current;
private int index = 0;
public ClassIterator(Node<Item> pre)
{
current = pre.next;
index = 1;
//System.out.println(current.item);
}
public boolean hasNext()
{
//System.out.println(current.item);
return current.next != null;
}
public void remove() { throw new UnsupportedOperationException(); }
public Item next()
{
if ( !hasNext() )
{
System.out.println("Queue is empty!!!");
throw new NoSuchElementException();
}
Item item = current.item;
current = current.next;
index++;
return item;
}
public void DisplayIndex( int indexVal )
{
if( index == indexVal ) System.out.println(current.item);
else {}
}//DisplayIndex ends
}//class ListIterator<Item> ends
public String toString()
{
StringBuilder s = new StringBuilder();
for (Item item : this) s.append(item + " ");
return s.toString();
}
/*
* Display at random based on the indices supplied from the main
*/
/*
* main function for unit testing
*/
public static void main(String[] args)
{
int N = Integer.parseInt(args[0]);
int K = Integer.parseInt(args[1]);
Deque<String> list = new Deque<String>();
System.out.println("Adding to the list by - addFirst");
for (int i = 0; i < N; i++) list.addFirst( StdIn.readString() );
StdOut.println(list);
StdOut.println();
Iterator<String> iter = list.iterator();
// print random index value
StdOut.println("Index Value = 1");
boolean a = iter.hasnext();
iter.DisplayIndex( 1 );
}//main ends
}
The problem is that i am not able to access hasnext() and DisplayIndex functions with ClassIterator even though i have created an object of Iterator. Any help ?
Check out my implemenation .... it works
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Deque<Item> implements Iterable<Item> {
private Node Head;
private Node Tail;
private int N;
private class Node{ // nested class to define nodes
Item item;
Node next;
Node previous;
}
public Deque() { // construct an empty deque
Head = null;
Tail = null;
}
public boolean isEmpty() { // is the deque empty?
return (Head == null && Tail == null);
}
public int size() { // return the number of items on the deque
return N;
}
public void addFirst(Item item) { // insert the item at the front
if(item == null)
throw new NullPointerException();
Node newNode = new Node();
newNode.item = item;
newNode.next = null;
newNode.previous = null;
if(Head == null && Tail == null) {
Head = newNode;
Tail = newNode;
}
else {
Node temp = Head;
Head = newNode;
newNode.next = temp;
temp.previous = newNode;
}
N++;
}
public void addLast(Item item) { // insert the item at the end
if(item == null)
throw new NullPointerException();
Node newNode = new Node();
newNode.item = item;
newNode.next = null;
newNode.previous = null;
if(Head == null && Tail == null) {
Head = newNode;
Tail = newNode;
}
else {
Tail.next = newNode;
newNode.previous = Tail;
Tail = newNode;
}
N++;
}
public Item removeFirst() { // delete and return the item at the front
if(isEmpty())
throw new NoSuchElementException();
Node temp = Head;
Head = Head.next;
Head.previous = null;
temp.next = null; // not required though its better to break the link
N--;
return temp.item;
}
public Item removeLast() { // delete and return the item at the end
if(isEmpty())
throw new NoSuchElementException();
Node temp = Tail;
Tail = Tail.previous;
Tail.next = null;
temp.previous = null;
N--;
return temp.item;
}
public Iterator<Item> iterator() { // return an iterator over items in order from front to end
return new dequeIterator<Item>();
}
#SuppressWarnings("hiding")
private class dequeIterator<Item> implements Iterator<Item> {
private Node current;
public dequeIterator() {
this.current = Head;
}
public boolean hasNext() {
//return ((current.next!=null)?true:false);
return current != null ;//&& current.next != null;
}
#SuppressWarnings("unchecked")
public Item next() {
if(!hasNext())
throw new NoSuchElementException();
Item temp = (Item) current.item;
current = current.next;
return temp;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
public void dispForward(){
Node temp = Head; //here did not assign memory as only reference was required
while(temp!=null) {
System.out.print(temp.item+" ");
temp = temp.next;
}
}
public void dispBackward(){
Node temp = Tail; //here did not assign memory as only reference was required
while(temp!=null) {
System.out.print(temp.item+ " ");
temp = temp.previous;
}
}
public static void main(String[] args) { // unit testing
Deque<Integer> de = new Deque<Integer>();
de.addFirst(10);
de.addFirst(9);
de.addFirst(8);
de.addLast(7);
de.addLast(6);
de.dispForward();
System.out.println();
System.out.println(de.removeLast());
System.out.println(de.removeFirst());
de.dispBackward();
System.out.println();
System.out.println("usnig iterator");
// using iterator
Iterator<Integer> itr = de.iterator();
while(itr.hasNext()) {
Object element = itr.next();
System.out.print(element + " ");
}
}
}
Related
Hi I'm trying to make remove method. But I don't know How to make this right. Here is my code.
This is LinkedList.java from Algorithm fourth edition.
/**
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin
* Wayne.
* #author Robert Sedgewick
* #author Kevin Wayne
*/
public class LinkedQueue<Item> implements Iterable<Item> {
private int N; // number of elements on queue
private Node first; // beginning of queue
private Node last; // end of queue
// helper linked list class
private class Node {
private Item item;
private Node next;
}
/**
* Initializes an empty queue.
*/
public LinkedQueue() {
first = null;
last = null;
N = 0;
assert check();
}
/**
* Is this queue empty?
* #return true if this queue is empty; false otherwise
*/
public boolean isEmpty() {
return first == null;
}
/**
* Returns the number of items in this queue.
* #return the number of items in this queue
*/
public int size() {
return N;
}
/**
* Returns the item least recently added to this queue.
* #return the item least recently added to this queue
* #throws java.util.NoSuchElementException if this queue is empty
*/
public Item peek() {
if (isEmpty()) throw new NoSuchElementException("Queue underflow");
return first.item;
}
/**
* Adds the item to this queue.
* #param item the item to add
*/
public void enqueue(Item item) {
Node oldlast = last;
last = new Node();
last.item = item;
last.next = null;
if (isEmpty()) first = last;
else oldlast.next = last;
N++;
assert check();
}
/**
* Removes and returns the item on this queue that was least recently added.
* #return the item on this queue that was least recently added
* #throws java.util.NoSuchElementException if this queue is empty
*/
public Item dequeue() {
if (isEmpty()) throw new NoSuchElementException("Queue underflow");
Item item = first.item;
first = first.next;
N--;
if (isEmpty()) last = null; // to avoid loitering
assert check();
return item;
}
/**
* Returns a string representation of this queue.
* #return the sequence of items in FIFO order, separated by spaces
*/
public String toString() {
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
}
// check internal invariants
private boolean check() {
if (N == 0) {
if (first != null) return false;
if (last != null) return false;
}
else if (N == 1) {
if (first == null || last == null) return false;
if (first != last) return false;
if (first.next != null) return false;
}
else {
if (first == last) return false;
if (first.next == null) return false;
if (last.next != null) return false;
// check internal consistency of instance variable N
int numberOfNodes = 0;
for (Node x = first; x != null; x = x.next) {
numberOfNodes++;
}
if (numberOfNodes != N) return false;
// check internal consistency of instance variable last
Node lastNode = first;
while (lastNode.next != null) {
lastNode = lastNode.next;
}
if (last != lastNode) return false;
}
return true;
}
//working properly
void reverseBystack(){
Stack<Item> s = new Stack<>();
Item item;
while (isEmpty() != true){
item = dequeue();
s.push(item);
}
while(s.isEmpty() != true){
item = s.pop();
enqueue(item);
}
}
//working properly.
void reverseBylink() {
Node prev = null;
Node current = this.first;
Node next = null;
Node temp = null;
while (current != null) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
temp =first;
first = last;
last = temp;
}
//How to do this...;<..
int remove(Item item) {
Node cur = this.first;
while (cur !=null) {
if (cur.item.equals(item)) {
item = dequeue();
}
cur = cur.next;
N++;
}
return 0;
}
/**
* Returns an iterator that iterates over the items in this queue in FIFO order.
* #return an iterator that iterates over the items in this queue in FIFO order
*/
public Iterator<Item> iterator() {
return new ListIterator();
}
// an iterator, doesn't implement remove() since it's optional
private class ListIterator implements Iterator<Item> {
private Node current = first;
public boolean hasNext() { return current != null; }
public void remove() { throw new UnsupportedOperationException(); }
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
}
Unit tests
/**
* Unit tests the <tt>LinkedQueue</tt> data type.
*/
public static void main(String[] args) {
LinkedQueue<String> q = new LinkedQueue<String>();
/* Working properly for reverseByStack.
q.enqueue("a");
q.enqueue("b");
q.enqueue("c");
q.enqueue("a");
q.enqueue("b");
q.enqueue("d");
q.enqueue("b");
q.enqueue("abba");
q.enqueue("a");
q.enqueue("z");
q.enqueue("a");
q.reverseBystack();
System.out.println(q);
StdOut.println("(" + q.size() + " left on queue)");
*/
/*Move on to next, working properly
q.enqueue("a");
q.enqueue("b");
q.enqueue("c");
q.enqueue("a");
q.enqueue("b");
q.enqueue("d");
q.enqueue("b");
q.enqueue("abba");
q.enqueue("a");
q.enqueue("z");
q.enqueue("a");
q.reverseBylink();
System.out.println(q);
StdOut.println("(" + q.size() + "left on queue)");*/
q.enqueue("a");
q.enqueue("b");
q.enqueue("c");
q.enqueue("a");
q.enqueue("b");
q.enqueue("d");
q.enqueue("b");
q.enqueue("abba");
q.enqueue("a");
q.enqueue("z");
q.enqueue("a");
System.out.println(q);
System.out.println("Remove some of elements. and use reverseByLink");
q.remove("a");
q.remove("f");
q.remove("c");
System.out.println(q);
}
Output.
a b c a b d b abba a z a
Remove some of elements. and use reverseByLink
a b d b abba a z a
I don't know why String a is not removed and after abba.
int remove(Item item) {
if(this.first == null)
return 0;
if(this.first == item) {
// remove root item
Node node = this.first.next;
this.first.next = null;
this.first = node;
return 1;
}
Node prv = this.first;
while (prv.next != item)
prv = prv.next;
// item was not found
if(prv == null)
return 0;
Node node = prv.next.next;
prv.next.next = null;
prv.next = node;
return 1;
}
I'm fairly sure this method is wrong:
int remove(Item item) {
Node cur = this.first;
while (cur !=null) {
if (cur.item.equals(item)) {
item = dequeue();
}
cur = cur.next;
N++;
}
return 0;
}
Your dequeue method pops the front of the list. But the item you're removing might not be the front of the list.
I didn't look for more problems.
This is standard linked list stuff. Some of your textbooks should have algorithms for this. But basically, you need to keep track of the last pointer you used. Let's say you have lastPtr and currentPtr, and you determine that currentPtr needs to go.
Then lastPtr.next = currentPtr.next
It's more interesting if you're at the head. You need to recognize that and instead do first.next = currentPtr.next.
dequeue() methods is popping out items from the front , but to remove all the occurrences of any string , you need to modify your remove() method to -
void remove(Item item) {
Node cur = this.first;
Node prev = null;
if(this.first.item.equals(item)){
item = dequeue();
cur = this.first;
}
while (cur != null) {
/* if (cur.item.equals(item)) {
item = dequeue();
}*/
while(cur != null && !cur.item.equals(item)) {
prev = cur;
cur = cur.next;
}
if(cur == null)
return;
prev.next = cur.next;
cur = prev.next;
}
return ;
}
I was given Bag class like this
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Bag<Item> implements Iterable<Item> {
private int N; // number of elements in bag
private Node<Item> first; // beginning of bag
// helper linked list class
private class Node<Item> {
private Item item;
private Node<Item> next;
}
/**
* Initializes an empty bag.
*/
public Bag() {
first = null;
N = 0;
}
/**
* Is this bag empty?
* #return true if this bag is empty; false otherwise
*/
public boolean isEmpty() {
return first == null;
}
/**
* Returns the number of items in this bag.
* #return the number of items in this bag
*/
public int size() {
return N;
}
/**
* Adds the item to this bag.
* #param item the item to add to this bag
*/
public void add(Item item) {
Node<Item> oldfirst = first;
first = new Node<Item>();
first.item = item;
first.next = oldfirst;
n++;
}
public void remove(Item item){
// currentNode is the reference to the first node in the list and to the Item
Node<Item> currentNode = first;
// if items equals the first node in the list, then first = currentNode.next which will make the first item
Node<Item> temp = currentNode;
while(temp.next != null){
temp = currentNode;
if(item.equals(currentNode.item)){
currentNode = currentNode.next;
temp.next = currentNode;
break;
}else{
currentNode = currentNode.next;
}
}
N--;
}
/**
* Returns an iterator that iterates over the items in the bag in arbitrary order.
* #return an iterator that iterates over the items in the bag in arbitrary order
*/
public ListIterator<Item> iterator() {
return new ListIterator<Item>(first);
}
// an iterator, doesn't implement remove() since it's optional
private class ListIterator<Item> implements Iterator<Item> {
private Node<Item> current;
public ListIterator(Node<Item> first) {
current = first;
}
public boolean hasNext() { return current != null; }
public void remove() { throw new UnsupportedOperationException(); }
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
}
As it can be seen,remove() method is an optional therefore it doesn't include the algorithm.
I wrote the remove method like this:
public void remove(Item item) {
Node<Item> currentNode = (Node<Item>) first;
Node<Item> previousNode = null;
while(currentNode != null){
if(item.equals(currentNode.item)){
if(previousNode == null) {
first = (Node<Item>) currentNode.next;
}
else {
previousNode.next = currentNode.next;
}
n--;
}
else {
previousNode = currentNode;
}
currentNode = currentNode.next;
}
}
However,
first = (Node<Item>) currentNode.next;
this line gives an "Type mismatch:Cannot convert from Bag.Node to Bag.Node" error which confuses me.
What should be done to overcome this error or is there a missing part in my remove method?
public class Bag<Item> implements Iterable<Item> {
// ...
private class Node<Item> {
// ...
}
// ...
}
This is defining two distinct type variables, both with the name Item.
If you want instances of Node to use the same type variable as the containing instance of Bag, remove the <Item> on Node:
private class Node {
I overcome this problem in this way.
public void removeAllOccurences(Item item){
Node<Item> currentNode = first;
Bag<Item> b = new Bag<Item>();
Bag<Item> reverseB = new Bag<Item>();
Node<Item> previous = new Node<Item>();
if(item.equals(first.item)){
first = currentNode.next;
N--;
currentNode = currentNode.next;
}
previous.item = currentNode.item;
b.add(previous.item);
currentNode = currentNode.next;
while(currentNode != null){
if(item.equals(currentNode.item))
{
previous.item = previous.item;
N--;
} else{
previous.item = currentNode.item;
b.add(previous.item);
}
currentNode = currentNode.next;
}
for(Item i: b)
reverseB.add(i);
this.first = reverseB.first;
}
If you want to test...
public static void main(String[] args) {
Bag<Integer> b = new Bag<Integer>();
Random rm = new Random();
for(int i =0; i < 10; i++)
b.add(rm.nextInt(3));
System.out.println("Bag before removing op: ");
for(Integer i: b)
System.out.print(" "+ i);
System.out.println("\nBag size BEFORE: "+b.size());
b.removeAllOccurences(2);
System.out.println("\nBag after removing op: ");
for(Integer i: b)
System.out.print(" "+ i);
System.out.println("\nBag size AFTER: "+b.size());
}
Output removing all occurrences of 2:
0 2 2 0 1 1 0 0 0 2
Bag size BEFORE: 10
Bag after removing op:
0 0 1 1 0 0 0
Bag size AFTER: 7
My code:
NOTE: Functions like readInt() and readString() are part of Princeton University's algs4.jar package.
import java.util.Iterator;
import java.util.NoSuchElementException;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
public class Deque < Item > implements Iterable < Item > {
private Node < Item > front;
private Node < Item > back;
private int numberOfItems;
private class Node < Item > {
Item item;
Node < Item > next;
Node < Item > prev;
}
public Deque() {
front = null;
back = null;
numberOfItems = 0;
}
public boolean isEmpty() {
return (numberOfItems == 0);
}
public int size() {
return numberOfItems;
}
public void addFirst(Item item) {
if (item == null) {
// When a null element is entered
throw new java.lang.NullPointerException("Item cannot be null");
}
Node < Item > newnode = new Node < Item > ();
newnode.item = item;
if (numberOfItems == 0) {
// When there are no elements
front = newnode;
back = newnode;
} else {
// When there are >=1 elements
newnode.prev = front;
newnode.next = null;
front.next = newnode;
front = newnode;
}
numberOfItems++;
}
public void addLast(Item item) {
if (item == null) {
// When a null element is entered
throw new java.lang.NullPointerException("Item cannot be null");
}
Node < Item > newnode = new Node < Item > ();
newnode.item = item;
if (numberOfItems == 0) {
// When there are no elements
front = newnode;
back = newnode;
} else {
// When there are >=1 elements
newnode.next = back;
newnode.prev = null;
back.prev = newnode;
back = newnode;
}
numberOfItems++;
}
public Item removeFirst() {
if (numberOfItems == 0) {
// When the deque is empty
throw new NoSuchElementException("No item to remove");
}
Item oldfirst = front.item;
if (numberOfItems == 1) {
front = null;
back = null;
} else {
front = front.prev;
}
numberOfItems--;
return oldfirst;
}
public Item removeLast() {
if (numberOfItems == 0) {
// When deque is empty
throw new NoSuchElementException("No item to remove");
}
Item oldlast = back.item;
if (numberOfItems == 1) {
front = null;
back = null;
} else {
back = back.next;
}
numberOfItems--;
return oldlast;
}
public Iterator < Item > iterator() {
return new ListIterator();
}
private class ListIterator implements Iterator < Item > {
private Node < Item > current = front;
public boolean hasNext() {
return (current != null);
}
public void remove() {
throw UnsupportedOperationException("remove is unsupported");
}
public Item next() {
Item item = current.item;
current = current.prev;
return item;
}
}
public static void main(String[] args) {
Deque < String > deq = new Deque();
String word;
while (!StdIn.isEmpty()) {
String cmd = StdIn.readString();
if (cmd.equals("af")) {
word = StdIn.readString();
deq.addFirst(word);
} else if (cmd.equals("al")) {
word = StdIn.readString();
deq.addFirst(word);
} else if (cmd.equals("rf")) {
deq.removeFirst();
} else if (cmd.equals("rl")) {
deq.removeLast();
} else if (cmd.equals("noi")) {
StdOut.println(deq.size());
}
}
}
}
I'm implementing the Deque as a collection of linked nodes. Each node has three characteristics- the content, a link to the next item and a link to the previous item. The class variables front and back are pointers for the first and the last element respectively.
When I was ran the program with my test client, I discovered that the method addLast(Item) here, inserts the item in the front instead of the rear.
Why is this happening? What is wrong with my logic?
Here is your addLast code
public void addLast(Item item) {
if (item == null) {
// When a null element is entered
throw new java.lang.NullPointerException("Item cannot be null");
}
Node < Item > newnode = new Node < Item > ();
newnode.item = item;
if (numberOfItems == 0) {
// When there are no elements
front = newnode;
back = newnode;
} else {
// When there are >=1 elements
newnode.next = back;
newnode.prev = null;
back.prev = newnode;
back = newnode;
}
numberOfItems++;
}
Note that when there's one node, the front and the back point to the same node. Then when you add the second node to the back, you assign back.prev to newnode, which is wrong. It should have been:
back.next = newnode;
newnode.prev = back;
back = newnode;
This is your code
public void addLast(Item item) {
if (item == null) {
// When a null element is entered
throw new java.lang.NullPointerException("Item cannot be null");
}
Node < Item > newnode = new Node < Item > ();
newnode.item = item;
if (numberOfItems == 0) {
// When there are no elements
front = newnode;
back = newnode;
} else {
// When there are >=1 elements
//**Here is the issue**
newnode.next = back;
newnode.prev = null;
back.prev = newnode;
back = newnode;
}
numberOfItems++;
}
Instead of
newnode.next = back;
newnode.prev = null;
back.prev = newnode;
back = newnode;
It should be
back.next = newnode;
newnode.prev=back;
newnode.next = null;
back = newnode
Hope this helps
I have an assignment to complete a DoublyLinkList assignment and I am having some difficulty with two of the methods. I was given the code for MyList and MyAbstractList and was told to extend MyAbstractList with my DoublyLinkedList. I am not allowed to change MyList or MyAbstractList.
Here is the code for MyList I was provided:
public interface MyList<E extends Comparable<E>> {
/** Return true if this list contains no elements */
public boolean isEmpty();
/** Return the number of elements in this list */
public int size();
/** Add a new element at the proper point */
public void add(E e);
/** Clear the list */
public void clear();
/** Return true if this list contains the element */
public boolean contains(E e);
/** Return the element from this list at the specified index */
public E get(int index);
/** Return the first element in the list */
public E getFirst();
/** Return the last element in the list */
public E getLast();
/** Return the index of the first matching element in this list.
* Return -1 if no match. */
public int indexOf(E e);
/** Return the index of the last matching element in this list
* Return -1 if no match. */
public int lastIndexOf(E e);
/** Remove the first occurrence of the element o from this list.
* Shift any subsequent elements to the left.
* Return true if the element is removed. */
public boolean remove(E e);
/** Remove the element at the specified position in this list
* Shift any subsequent elements to the left.
* Return the element that was removed from the list. */
public boolean remove(int index);
/** Remove the first element in the list, return true if done, false if list is empty */
public boolean removeFirst();
/** Remove the Last element in the list, return true if done, false if list is empty */
public boolean removeLast();
/** Replace the element at the specified position in this list
* with the specified element and return true if done, false if index out of range. */
public boolean set(int index, E e);
}
and this was the code I was provided for MyAbstractList:
public abstract class MyAbstractList<E extends Comparable<E>> implements MyList<E> {
protected int size = 0; // The size of the list
/** Create a default list */
protected MyAbstractList() {
}
/** Create a list from an array of objects */
public MyAbstractList(E[] objects) {
for (int i = 0; i < objects.length; i++)
add(objects[i]);
}
#Override /** Return true if this list contains no elements */
public boolean isEmpty() {
return size == 0;
}
#Override /** Return the number of elements in this list */
public int size() {
return size;
}
}
Finally here is my code for MyDoublyLinkedList:
import java.util.ArrayList;
public class MyDoublyLinkedList<E extends Comparable<E>> extends MyAbstractList<E>
{
int size =0;
Node<E> head = null;
Node<E> current = null;
Node<E> tail = null;
public MyDoublyLinkedList() {
}
/** Create a list from an array of objects */
public MyDoublyLinkedList(E[] objects) {
super(objects);
}
#Override
public boolean isEmpty()
{
return size == 0;
}
#Override
public int size()
{
return size;
}
/** Add a new element at the proper point */
#Override
public void add(E e)
{
Node<E> newNode = new Node<E>(e);
if (tail == null) {
head = tail = newNode;
}
else //if (head != null)
{
tail.next = newNode;
tail = newNode;
}
size++;
}
#Override
public void clear()
{
size = 0;
head = tail = null;
}
#Override
public boolean contains(E e)
{
Node<E> current = head;
for (int i = 0; i < size; i++) {
if (current.element.equals(e))
return true;
current = current.next;
}
return false;
}
#Override
public E get(int index)
{
if (index < 0 || index > size - 1)
return null;
Node<E> current = head;
for (int i = 0; i < index; i++)
current = current.next;
return current.element;
}
#Override
public E getFirst()
{
if (size == 0) {
return null;
}
else {
return head.element;
}
}
#Override
public E getLast()
{
if (size == 0) {
return null;
}
else {
return tail.element;
}
}
#Override
public int indexOf(E e)
{
Node<E> current = head;
for (int i = 0; i < size; i++) {
if (current.element.equals(e))
return i;
current = current.next;
}
return -1;
}
#Override
public int lastIndexOf(E e)
{
int lastIndex = -1;
Node<E> current = head;
for (int i = 0; i < size; i++) {
if (current.element.equals(e))
lastIndex = i;
current = current.next;
}
return lastIndex;
}
/** Remove the first occurrence of the element o from this list.
* Shift any subsequent elements to the left.
* Return true if the element is removed. */
#Override
public boolean remove(E e)
{
int index = indexOf(e);
if (index != -1) {
return remove(index);
} else {
return false;
}
}
/** Remove the element at the specified position in this list
* Shift any subsequent elements to the left.
* Return the element that was removed from the list. */
#Override
public boolean remove(int index)
{
if (index < 0 || index >= size) {
return false;
}
else if (index == 0) {
return removeFirst();
}
else if (index == size - 1) {
return removeLast();
}
else {
Node<E> previous = head;
for (int i = 1; i < index; i++) {
previous = previous.next;
}
Node<E> current = previous.next;
previous.next = current.next;
size--;
return true;
}
}
#Override
public boolean removeFirst()
{
if (size == 0) {
return false;
}
else {
Node<E> temp = head;
head = head.next;
size--;
if (head == null) {
tail = null;
}
return true;
}
}
#Override
public boolean removeLast()
{
if (size == 0) {
return false;
}
else if (size == 1) {
Node<E> temp = head;
head = tail = null;
size = 0;
return true;
}
else {
Node<E> current = head;
for (int i = 0; i < size - 2; i++) {
current = current.next;
}
Node<E> temp = tail;
tail = current;
tail.next = null;
size--;
return true;
}
}
#Override
public boolean set(int index, E e)
{
if (index < 0 || index > size - 1)
return false;
Node<E> current = head;
for (int i = 0; i < index; i++)
current = current.next;
E temp = current.element;
current.element = e;
return true;
}
#Override
public String toString()
{
StringBuilder result = new StringBuilder("[");
Node<E> current = head;
for (int i = 0; i < size; i++) {
result.append(current.element);
current = current.next;
if (current != null) {
result.append(", "); // Separate two elements with a comma
}
else {
result.append("]"); // Insert the closing ] in the string
}
}
return result.toString();
}
public String toStringBack()
{
StringBuilder result = new StringBuilder("[");
Node<E> current = tail;
for (int i = 0; i < size; i++) {
result.append(current.element);
current = current.previous;
if (current != null) {
result.append(", "); // Separate two elements with a comma
}
else {
result.append("]"); // Insert the closing ] in the string
}
}
return result.toString();
}
public void add(int index, E e)
{
if (index ==0) {
addFirst(e);// The new node is the only node in list
}
else if(index > size)
{
addLast(e);//The index location was bigger than size
}
else
{
Node<E> current = getAtIndex(index-1);
Node<E> temp = current.next;
current.next = new Node<E>(e);
(current.next).next = temp;
size++;
}
}
public void addFirst(E e)
{
Node<E> newNode = new Node<E>(e); // Create a new node
newNode.next = head; // link the new node with the head
head = newNode; // head points to the new node
size++; // Increase list size
if (tail == null) // the new node is the only node in list
tail = head;
}
public void addLast(E e)
{
Node<E> newNode = new Node<E>(e); // Create a new for element e
if (tail == null) {
head = tail = newNode; // The new node is the only node in list
}
else {
tail.next = newNode; // Link the new with the last node
tail = tail.next; // tail now points to the last node
}
size++;
}
protected Node<E> getAtIndex(int index)
{
int count;
if (index < 0 || index > size - 1)
return null;
Node<E> temp = null;
if(index <= (size/2))
{
count = -1;
temp = head;
while(++count <= index){
temp = temp.next;
}
}
else if (index > (size/2))
{
count = size;
temp = tail;
while(--count >= index){
temp = temp.previous; //--> this is Where the null pointer exception occurs
}
}
return temp;
}
private static class Node<E>{
E element;
Node<E> next;
Node<E> previous;
public Node(E element){
this.element = element;
next = null;
previous = null;
}
}
}
When I run the add(int index, E e) Method I receive a null pointer exception in the getAtIndext() method. I also have had issues getting the add(E e) Method to add properly when I change the current location. The methods are all as I am being required to use them. The use of iterators while they would be nice are not allowed. I am using Bluj as a compiler. Please let me know what questions you have.
Thank you
EDIT: I do know what a Null Pointer Exception is, I can not figure out why this is coming back as null. The Node "current" should point to the end, then go back in the list until it reaches the indexed location. This only happens when I try to add a node in the last half of the list. The error is thrown at temp = temp.previous;
The stack trace is:
java.lang.NullPointerException at MyDoublyLinkedList.getAtIndex(MyDoublyLinkedList.java:345) at MyDoublyLinkedList.add(MyDoublyLinkedList.java:289) at TestMyDoublyLinkedList.main(TestMyDoublyLinkedList.java:50)
Edit: I figured out the issue. The add() and getAtIndex functions are running properly. When I run the test the function that is throwing a Null Pointer Exception is throwing it at position 8. It cycles through the first few nodes fine, but dies at node 8
When inserting in the add() method, you never assign previous so it is null for all nodes.
This is a homework question. I have a Double Linked Node class, Circular Double Linked List class which implements Iterable, and a Iterator class that implements Iterator. I understand the concept of an iterator where an implicit cursor sits between two nodes and on a call to next() it returns the node it just jumped over. I created a test class with a new list object. I then created an iterator and called next, I received the correct No Such Element exception but when I added some nodes to the list I received a Null Pointer Exception instead of it returning the last returned node. How can I correct this?
My Node class:
public class DoubleLinkedNode<E>{
private E data;
private DoubleLinkedNode<E> next;
private DoubleLinkedNode<E> prev;
public DoubleLinkedNode(E data, DoubleLinkedNode<E> next, DoubleLinkedNode<E> prev){
this.data = data;
this.next = next;
this.prev = prev;
}
/**
* Used to construct a node that points to null for its prev and next.
* #param data Data is a generic variable to be stored in the node.
*/
public DoubleLinkedNode(E data){
this(data, null, null);
}
//getters
public E getData(){
return data;
}
public DoubleLinkedNode<E> getNext(){
return next;
}
public DoubleLinkedNode<E> getPrev(){
return prev;
}
//setters
public void setData(E data){
this.data = data;
}
public void setNext(DoubleLinkedNode<E> next){
this.next = next;
}
public void setPrev(DoubleLinkedNode<E> prev){
this.prev = prev;
}
#Override public String toString(){
if(data == null){
return null;
}
else{
return data.toString();
}
}
}
The List class with the private inner Iterator class:
import java.util.Iterator;
import java.util.ListIterator;
import java.util.NoSuchElementException;
public class CircularDoubleLinkedList<E> implements Iterable<E>{
private int size;
private DoubleLinkedNode<E> head;
public CircularDoubleLinkedList(){
this.head = null;
this.size = 0;
}
/**
* Adds an item to the end of the list.
*
* #param data The Data that is to be stored in the node.
*/
public void add(E data){
DoubleLinkedNode<E> newNode = new DoubleLinkedNode<E>(data);
if(this.head == null){
newNode.setNext(newNode);
newNode.setPrev(newNode);
this.head = newNode;
this.size++;
//if list is empty create a new node and insert
}
else{
DoubleLinkedNode<E> temp = this.head.getPrev();
this.head.getPrev().setNext(newNode);
this.head.setPrev(newNode);
newNode.setPrev(temp);
newNode.setNext(this.head);
this.size++;
}
}
/**
* Which adds an item at the specified index.
*
* #param index The index in which the new Node is added.
* #param data The data which is to be stored in the node.
*/
public void add(int index, E data){
int currIndex = 0;
DoubleLinkedNode<E> currNode = this.head;
DoubleLinkedNode<E> nextNode = this.head.getNext();
DoubleLinkedNode<E> prevNode = this.head.getPrev();
DoubleLinkedNode<E> newNode = new DoubleLinkedNode<E>(data);
if(index == 0){
prevNode.setNext(newNode);
currNode.setPrev(newNode);
newNode.setPrev(prevNode);
newNode.setNext(currNode);
this.head = newNode;
this.size++;
}
else if (index > 0){
while(currIndex != this.size){
if(currIndex != index%size){
currIndex++;
currNode = currNode.getNext();
nextNode = nextNode.getNext();
prevNode = prevNode.getNext();
}else{
newNode.setPrev(prevNode);
newNode.setNext(currNode);
prevNode.setNext(newNode);
currNode.setPrev(newNode);
currNode = newNode;
this.size++;
break;
}
}
}
else if (index < 0){
while(currIndex != -this.size){
if(currIndex != index%size){
currIndex--;
currNode = currNode.getPrev();
prevNode = prevNode.getPrev();
nextNode = nextNode.getPrev();
}else{
newNode.setNext(nextNode);
newNode.setPrev(currNode);
currNode.setNext(newNode);
nextNode.setPrev(newNode);
currNode = newNode;
this.size++;
break;
}
}
}
}
/**
* Returns the data stored at the specified index.
*
* #param index The index determines the node whose data is returned.
* #return Returns the data of the node at the index.
*/
public E get(int index){//returns the data stored at the specified index
int currIndex = 0;
DoubleLinkedNode<E> currNode = this.head;
E temp = null;
if(index == 0){//zero case
temp = currNode.getData();
}
else if(index > 0){//positive
while(currIndex != this.size){
if(currIndex != index%size){
currIndex++;
currNode = currNode.getNext();
}else{
temp = currNode.getData();
break;
}
}
}
else if(index < 0){//negative
while(currIndex != -this.size){
if(currIndex != index%size){
currIndex--;
currNode = currNode.getPrev();
}else{
temp = currNode.getData();
break;
}
}
}
return temp;
}
/**
* Which removes and returns an item from the list.
*
* #param index Removes the node at the current index.
* #return Returns the data of the removed node.
*/
public E remove(int index){//which removes and returns an item from the list
int currIndex = 0;
DoubleLinkedNode<E> currNode = this.head;
DoubleLinkedNode<E> nextNode = this.head.getNext();
DoubleLinkedNode<E> prevNode = this.head.getPrev();
E temp = null;
if(index == 0){
temp = currNode.getData();
prevNode.setNext(currNode.getNext());
nextNode.setPrev(currNode.getPrev());
this.head = nextNode;
size--;
}
else if(index > 0){//positive
while(currIndex != this.size){
if(currIndex != index%size){
currIndex++;
currNode = currNode.getNext();
nextNode = nextNode.getNext();
prevNode = prevNode.getNext();
}else{
temp = currNode.getData();
prevNode.setNext(currNode.getNext());
nextNode.setPrev(currNode.getPrev());
currNode = nextNode;
size--;
break;
}
}
}
else if(index < 0){//negative
while(currIndex != -this.size){
if(currIndex != index%size){
currIndex--;
currNode = currNode.getPrev();
prevNode = prevNode.getPrev();
nextNode = nextNode.getPrev();
}else{
temp = currNode.getData();
prevNode.setNext(currNode.getNext());
nextNode.setPrev(currNode.getPrev());
currNode = prevNode;
size--;
break;
}
}
}
return temp;
}
/**
* Returns the size.
*
* #return
*/
public int size(){
return size;
}
#Override public String toString(){
String str = "[";
int index = 0;
DoubleLinkedNode<E> curr = head;
if(size == 0){
return "There is no one here to kill.";
}else{
while (index <this.size) {
str += curr.getData();
curr = curr.getNext();
index++;
if (index<this.size) {
str += ", ";
}
}
str += "]";
}
return str;
}
#Override
public Iterator<E> iterator() {
return new CircularDoubleIterator();
}
// Iterator inner class begins
private class CircularDoubleIterator implements ListIterator<E> {
private DoubleLinkedNode<E> nextItem;//reference to next item
private int index = 0;
private DoubleLinkedNode<E> lastReturned;// the last node to be returned by prev() or next()
// reset to null after a remove() or add()
#Override
public E next() {
if(!hasNext()){
throw new NoSuchElementException("No such element.");
}
else{
nextItem = head; //edited 11Sept13
lastReturned = nextItem.getNext();
nextItem = nextItem.getNext();
head = nextItem; //edited 11Sept13
index++;
return lastReturned.getData();
}
}
#Override
public E previous() {
if(!hasPrevious()){
throw new NoSuchElementException("No such element.");
}
else{
index--;
return ;
}
}
#Override
public int nextIndex() {
return index;
}
#Override
public int previousIndex() {
return index-1;
}
#Override
public boolean hasNext() {
return size != 0;
}
#Override
public boolean hasPrevious() {
return size!= 0;
}
#Override
public void remove() {
}
#Override
public void set(E theData) {
if(lastReturned == null){
throw new IllegalStateException();
}
else{
}
}
#Override
public void add(E theData) {
if(size == 0){
}
else if(size != 0){
}
}
}
//Iterator inner class ends
}
I don't see where you assign values to private DoubleLinkedNode<E> nextItem; when you create iterator.
I cannot see the whole code. So I assume that nextItem is null or its next field is null.