Lesson notes
These notes explain the problem and current implementation. They are a reading companion, not a verbatim transcript of the recording.
This lesson implements linked-list operations from a head node, then compares them with a doubly linked wrapper that retains a tail and length. Those interfaces expose different information. An operation that is direct with a saved tail may require traversal when the function receives only a head.
Make head replacement part of the contract
Prepending creates a node whose next reference points to the old head, then returns the new node. The caller must retain that returned head. Appending from a head-only interface follows successors until it reaches the final node, then attaches the new node. Empty input needs a separate path because there is no final node to update.
For an insertion into the middle, first locate the predecessor. Set the new node's next reference to the predecessor's old successor before connecting the predecessor to the new node. This order preserves the remaining chain. Removing a node similarly reconnects its predecessor to its successor. Removing the head changes the returned head instead.
Maintain both directions in a doubly linked wrapper
A wrapper with head, tail, and length must keep them consistent after every mutation. In a nonempty doubly linked list, a next link and the corresponding previous link should agree. Prepending changes the old head's previous reference; appending changes the old tail's next reference. An empty-to-nonempty transition must establish both endpoints.
The constructor in the current example creates a first node, so its initial length is one. A zero initial count would make later increments disagree with the chain. Test the constructor state before testing any method. A correct append cannot repair a count that was already wrong.
Charge for the traversal you perform
Given the needed predecessor, changing a fixed number of links uses constant work. Finding a position from the head takes linear time. Retaining a tail makes append direct, but removing a singly linked tail still requires finding its predecessor. A recursive traversal also adds stack depth that a loop avoids.
Check an empty chain, one node, insertion at the head, and insertion at the end. Walk forward after every mutation and backward for the doubly linked version. Use the current implementation lesson for its exact index contracts, then apply the same reference discipline to Reverse a Linked List.