Reputation: 125
I'm doing this small project of creating a queue and a de-queue in the same class along with using my own Node class and an interface.
The problem i'm facing is I've done all methods but can't get the method removeLast to work because i'm unable to let rear link to the node before it, after getting removed. Please help me with your suggestions? Thank you.
My node class.
public class Node<T> {
T info;
Node<T> next;
public Node(T element) {
info = element;
next = null;
}
public void setInfo(T element) {
info = element;
}
public T getInfo() {
return info;
}
public void setNext(Node<T> next) {
this.next = next;
}
public Node<T> getNext() {
return next;
}
}
My interface class
public interface DequeInterface<T> {
void addFront(T element);
void addLast(T element);
T removeFront();
T removeLast();
boolean isEmpty();
int getSize();
}
My deque class
import java.util.NoSuchElementException;
public class Deqeue<T> implements DequeInterface {
public Node<T> front;
public Node<T> rear;
int size;
public Deqeue() {
front = null;
rear = null;
size = 0;
}
@Override
public T removeFront() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = front.getInfo();
front = front.getNext();
size--;
return element;
}
@Override
public T removeLast() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = rear.getInfo();
size--;
return element;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return rear == null;
}
@Override
public void addFront(Object element) {
Node<T> newNode = front;
if (newNode == null) {
rear = front;
}
front = new Node(element);
front.setNext(newNode);
size++;
}
@Override
public void addLast(Object element) {
Node<T> newNode = rear;
if (newNode == null) {
front = rear;
}
rear = new Node(element);
newNode.setNext(rear);
size++;
}
}
Upvotes: 3
Views: 6640
Reputation: 5944
You could have your Node
have a reference to the previous Node
as well. This would create a doubly linked list.
public class Node<T> {
T info;
Node<T> next;
Node<T> prev;
public Node(T element) {
info = element;
next = null;
prev = null;
}
public void setInfo(T element) {
info = element;
}
public T getInfo() {
return info;
}
public void setNext(Node<T> next) {
this.next = next;
}
public Node<T> getNext() {
return next;
}
public void setPrev(Node<T> prev) {
this.prev = prev;
}
public Node<T> getPrev() {
return prev;
}
}
Then in the Deque
class change your removeFront
and removeLast
methods to account for prev
public T removeFront() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = front.getInfo();
front = front.getNext();
front.setPrev(null); //<<<--------------------------
size--;
return element;
}
@Override
public T removeLast() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = rear.getInfo();
rear.getPrev().setNext(null) //<<<--------------
rear=rear.getPrev(); //<<<--------------
size--;
return element;
}
And of course the addFirst
and addLast
methods have to be updated as well
@Override
public void addFront(Object element) {
Node<T> newNode = front;
front = new Node(element);
front.setNext(newNode);
if (newNode == null) {
rear = front;
}else{
newNode.setPrev(front);
}
size++;
}
@Override
public void addLast(Object element) {
Node<T> newNode = rear;
rear = new Node(element);
newNode.setNext(rear);
if (newNode == null) {
front = rear;
}else{
newNode.setNext(rear);
}
size++;
}
If you would not be allowed to change the code of Node
and only can change the removeLast()
method then you could do it like this:
@Override
public T removeLast() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = rear.getInfo();
if(rear==first){
rear=null;
first=null;
}else{
Node<T> prev = first;
while(prev.getNext()!=rear){
prev=prev.getNext();
}
rear=prev;
prev.setNext(null);
}
size--;
return element;
}
But this would be rather inefficient as it requires iterating through the whole list from the beginning.
Upvotes: 1
Reputation: 289
The easiest way to go about doing this is to implement a doubly linked list as opposed to a linked list. So your node class will need to keep track of the previous element. You will need to update your add functions to support this. Once completed, your remove last function will look like this:
@Override
public T removeLast() {
if (isEmpty()) {
throw new NoSuchElementException();
}
T element = rear.getInfo();
size--;
rear.getPrev().setNext(null);
rear = rear.getPrev();
return element;
}
Upvotes: 0
Reputation: 26117
The problem is that your list is singly-linked. Unfortunately, removing the last node of a singly-linked list requires traversing the entire list. Some alternatives:
Upvotes: 2
Reputation: 26574
You can make your list doubly linked (extra management and opportunity for bugs), or you can iterate through the list every time you removeLast and set rear to the new last (much worse performance when removing from last especially on large lists.)
Upvotes: 0
Reputation: 691775
Each node should have a pointer to the next node and to the previous node.
Upvotes: 0