I have to implement a singly linked list for my project and I'm having trouble getting the remove method to work. I have searched on here for answers but I can't find any that incorporate the tail reference. My project needs to have a head and tail reference in the list and needs to be updated wherever necessary. This is my class and the remove method:
public class BasicLinkedList<T> implements Iterable<T> {
public int size;
protected class Node {
protected T data;
protected Node next;
protected Node(T data) {
this.data = data;
next = null;
}
}
protected Node head;
protected Node tail;
public BasicLinkedList() {
head = tail = null;
}
public BasicLinkedList<T> addToEnd(T data) {
Node n = new Node(data);
Node curr = head;
//Check to see if the list is empty
if (head == null) {
head = n;
tail = head;
} else {
while (curr.next != null) {
curr = curr.next;
}
curr.next = n;
tail = n;
}
size++;
return this;
}
public BasicLinkedList<T> addToFront(T data) {
Node n = new Node(data);
if(head == null){
head = n;
tail = n;
}
n.next = head;
head = n;
size++;
return this;
}
public T getFirst() {
if (head == null) {
return null;
}
return head.data;
}
public T getLast() {
if(tail == null){
return null;
}
return tail.data;
}
public int getSize() {
return size;
}
public T retrieveFirstElement() {
// Check to see if the list is empty
if (head == null) {
return null;
}
Node firstElement = head;
Node curr = head.next;
head = curr;
size--;
return firstElement.data;
}
public T retrieveLastElement() {
Node curr = head;
Node prev = head;
// Check to see if the list is empty
if (head == null) {
return null;
} else {
// If there's only one element in the list
if (head.next == null) {
curr = head;
head = null;
} else {
while (curr.next != null) {
prev = curr;
curr = curr.next;
}
tail = prev;
tail.next = null;
}
}
size--;
return curr.data;
}
public void remove(T targetData, Comparator<T> comparator) {
Node prev = null, curr = head;
while (curr != null) {
if (comparator.compare(curr.data, targetData) == 0) {
//Check to see if we need to remove the very first element
if (curr == head) {
head = head.next;
curr = head;
}
//Check to see if we need to remove the last element, in which case update the tail
else if(curr == tail){
curr = null;
tail = prev;
prev.next = null;
}
//If anywhere else in the list
else {
prev.next = curr.next;
curr = curr.next;
}
size--;
} else {
prev = curr;
curr = curr.next;
}
}
}
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.");
}
};
}
}
I have went through many iterations of this method and each time I either lose the head reference, the tail reference or I don't remove the element and I am stumped trying to figure it out. For reference here is the test I'm running on it. I don't even fail the test, it just says failure trace.
public void testRemove(){
BasicLinkedList<String> basicList = new BasicLinkedList<String>();
basicList.addToEnd("Blue");
basicList.addToEnd("Red");
basicList.addToEnd("Magenta");
//Blue -> Red -> Magenta -> null
basicList.remove("Red", String.CASE_INSENSITIVE_ORDER);
//Blue -> Magenta -> null
assertTrue(basicList.getFirst().equals("Blue"));
//getLast() returns the tail node
assertTrue(basicList.getLast().equals("Magenta"));
}
EDIT: Forgot to mention that the remove method should be removing all instances of the target data from the list.
I see only 1 bug. If your list is initially empty the following method will cause a loop where you have one node whose next refers to itself:
public BasicLinkedList<T> addToFront(T data) {
Node n = new Node(data);
// The list was empty so this if is true
if(head == null){
head = n;
tail = n;
}
n.next = head;
// now head == n and n.next == head == n so you've got a circle
head = n;
size++;
return this;
}
You can fix this like so:
public BasicLinkedList<T> addToFront(T data) {
Node n = new Node(data);
if(head == null){
tail = n;
}
n.next = head;
head = n;
size++;
return this;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With