Say we want to remove the third element from our linked list (index 2). Based on the previous section, we might start by making a current pointer that points at the head of the list and then advancing it 2 times.
Now imagine what needs to happen to successfully remove the node containing 8. We need to delete the node that contains 8. But we also need to change the next pointer in the node containing 15 so that it points to the node containing 12. That way the list remains connected after we delete the 8 node.
But how do we get access to the node containing 15? Our current pointer is pointing at the 8 node, and we have no way to get back to the previous node in the list! Our SimpleLinkedList is what is referred to as a singly linked list - each node only has a pointer to the next node in the list, and no pointer to the previous node.
As with storing the size of the list, adding pointers to previous nodes would make certain operations easier, but it would also add complexity and overhead to every operation that modifies the list. We will explore doing so later. For now, we will stick with a singly linked list and figure out how to work within its limitations.
Although we canβt reach back to access the previous node, it is easy to reach forward. If we advance our current pointer one less time, it will be pointing at the node before the one we want to remove (15 in this list). From there, we can access the node we want to remove (the 8 node) via the next pointer.
You can click and drag on the animation area to pan around. Use the Ctrl + mouse wheel (or touchpad scroll gesture) while over the animation area to zoom in and out.
void SimpleLinkedList<T>::removeAt(int index) {
ListNode<T>* current = head;
// Move current to the node before the desired index
for(int i = 0; i < index - 1; i++) {
current = current->next;
}
ListNode<T>* toDelete = current->next;
current->next = toDelete->next;
delete toDelete;
}
This code assumes that the index is valid. In a real implementation, we would need to add checks for negative indices and indices that are too large. (For the rest of the SimpleLinkedList methods, we will omit bounds checking for simplicity.)
Our logic assumes we will be modifying the node before the one we want to remove, but there is no node before the first node! The first node is a special caseβit is tracked by the head pointer instead of the next pointer of a previous node.
void SimpleLinkedList<T>::removeAt(int index) {
if(index == 0) {
removeStart();
return;
}
ListNode<T>* current = head;
// Move current to the node before the desired index
for(int i = 0; i < index - 1; i++) {
current = current->next;
}
ListNode<T>* toDelete = current->next;
current->next = toDelete->next;
delete toDelete;
}
Checkpoint27.9.1.
Instead of advancing the current pointer index - 1 times, we can use a trailing pointer that is always one node behind the current pointer. Design the logic for this approach.