Simple Doubly Linked List Erase Implementation video (20 minutes) (Spring 2021)
We will now implement an erase()
function, which will delete an existing Node from a a Doubly Linked List.
Behavior will be modeled after std::list::erase
, with a few key points
erase()
function accepts a "position" Iterator parameter, and will delete the Node at this positionerase()
function returns an Iterator pointing to the Node AFTER the Node deleted by the function call.https://www.cplusplus.com/reference/list/list/erase/
erase()
callIn general, if deleting a Node at Iterator location "to_delete", the following pointers will need to be updated, for a Doubly Linked List:
to_delete->prev->next = to_delete->next
to_delete->next->prev = to_delete->prev
These two pointer updates accomplish "cutting out the middle man", or, setting the two adjacent Nodes, on either side of the deleted Node, to point to each other, as next
and prev
.
erase()
from a ListThere are four possible scenarios for deleting from a list. If they are handled in a specific order, the possibility of null pointer references are eliminated by the time you get to the final, general case, of "deleting an existing Node in between two existing Nodes".
head == tail
The following code example is written to reflect this order. In scenarios 1, 2, and 3, there are possibilities of null pointer references, eg, when deleting the head of a list, to_delete->prev
will be nullptr. (So you would not want to try and set to_delete->prev->next = to_delete->next
, as there is no to_delete->prev
.)
erase()
function codeThis is a public member function of the LinkedList
class, our implementation of a Doubly Linked List.
Iterator erase(Iterator position) {
if (position.cur == nullptr) {
throw std::exception(); // TODO throw a specific exception
}
// Single element case
if (head == tail) {
if (position.cur != head) {
throw std::exception(); // TODO throw a specific exception
}
head = tail = nullptr;
delete position.cur;
return end();
} else if (position.cur == head) { // Erasing head
head = position.cur->next;
head->prev = nullptr;
delete position.cur;
return Iterator(head);
} else if (position.cur == tail) { // Erasing tail
tail = position.cur->prev;
tail->next = nullptr;
delete position.cur;
return end();
} else { // General case: erasing between head and tail
position.cur->prev->next = position.cur->next;
position.cur->next->prev = position.cur->prev;
Iterator next_position = position;
++next_position;
delete position.cur;
return next_position;
}
}
Thanks to Brian Foster for typing up the rough draft of these notes based on the lecture video.