0
0
DSA Pythonprogramming~10 mins

Insert at End of Doubly Linked List in DSA Python - Execution Trace

Choose your learning style9 modes available
Concept Flow - Insert at End of Doubly Linked List
Create new node with data
↓
Is list empty? head == None
↓
Set head = new
↓
Traverse to last node
↓
Set last.next = new
↓
Set new.prev = last
↓
Done
Create a new node, check if list is empty, if yes set head to new node. Otherwise, traverse to last node, link last node's next to new node, and new node's prev to last node.
Execution Sample
DSA Python
class Node:
    def __init__(self, data):
        self.data = data
        self.prev = None
        self.next = None

def insert_end(head, data):
    new_node = Node(data)
    if head is None:
        head = new_node
        return head
    current = head
    while current.next:
        current = current.next
    current.next = new_node
    new_node.prev = current
    return head

# Example usage:
head = Node(10)
second = Node(20)
third = Node(30)
head.next = second
second.prev = head
second.next = third
third.prev = second

# Insert 40 at end
head = insert_end(head, 40)
Insert a new node with value 40 at the end of a doubly linked list starting at head.
Execution Table
StepOperationNodes in ListPointer ChangesVisual State
1Create new node with data=4010 <-> 20 <-> 30new_node.prev = None, new_node.next = Noneβ”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ data:10β”‚ β”‚ data:20β”‚ β”‚ data:30β”‚ β”‚ prev:βˆ… β”‚ β”‚ prev───┼──→ β”‚ prev───┼──→ β”‚ β”‚ next───┼──→ β”‚ next───┼──→ β”‚ next:βˆ… β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ head
2Check if head is None10 <-> 20 <-> 30head is not None, proceed to traverseSame as above
3Traverse to last node (30)10 <-> 20 <-> 30current moves from 10 to 20 to 30Same as above, pointer current at node 30
4Set last.next = new_node10 <-> 20 <-> 3030.next = new_nodeβ”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ data:10β”‚ β”‚ data:20β”‚ β”‚ data:30β”‚ β”‚ data:40β”‚ β”‚ prev:βˆ… β”‚ β”‚ prev───┼──→ β”‚ prev───┼──→ β”‚ prev:βˆ… β”‚ β”‚ next───┼──→ β”‚ next───┼──→ β”‚ next───┼──→ β”‚ next:βˆ… β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ head
5Set new_node.prev = last node (30)10 <-> 20 <-> 30 <-> 40new_node.prev = 30β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ data:10β”‚ β”‚ data:20β”‚ β”‚ data:30β”‚ β”‚ data:40β”‚ β”‚ prev:βˆ… β”‚ β”‚ prev───┼──→ β”‚ prev───┼──→ β”‚ prev───┼──→ 30 β”‚ next───┼──→ β”‚ next───┼──→ β”‚ next───┼──→ β”‚ next:βˆ… β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ head
6Insertion complete10 <-> 20 <-> 30 <-> 40Pointers stableβ”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ data:10β”‚ β”‚ data:20β”‚ β”‚ data:30β”‚ β”‚ data:40β”‚ β”‚ prev:βˆ… β”‚ β”‚ prev───┼──→ β”‚ prev───┼──→ β”‚ prev───┼──→ β”‚ next───┼──→ β”‚ next───┼──→ β”‚ next───┼──→ β”‚ next:βˆ… β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ head
πŸ’‘ Insertion done after last node, new node's next is None
Variable Tracker
VariableStartAfter Step 1After Step 3After Step 4After Step 5Final
headNode(10)Node(10)Node(10)Node(10)Node(10)Node(10)
currentNoneNoneNode(30)Node(30)Node(30)Node(30)
new_nodeNoneNode(40)Node(40)Node(40)Node(40)Node(40)
Key Moments - 3 Insights
Why do we check if head is None before inserting?
If head is None, the list is empty, so the new node becomes the head. This is shown in step 2 of the execution_table where we decide to traverse or set head.
Why do we set new_node.prev to last node?
Because in a doubly linked list, each node points back to its previous node. Step 5 shows setting new_node.prev to the last node to maintain backward links.
How do we know where the last node is?
We traverse starting from head until current.next is None, meaning current is the last node. Step 3 shows this traversal.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the value of 'current' after step 3?
ANode with data 20
BNode with data 30
CNode with data 40
DNone
πŸ’‘ Hint
Check the 'current' variable in variable_tracker after step 3
At which step is the new node's prev pointer set to the last node?
AStep 5
BStep 4
CStep 2
DStep 6
πŸ’‘ Hint
Look at the Pointer Changes column in execution_table rows
If the list was empty initially, what would be the visual state after insertion?
ANo nodes, head is None
BTwo nodes linked together
CSingle node with prev and next as None, head points to it
DNew node with next pointing to head
πŸ’‘ Hint
Refer to concept_flow branch when head is None
Concept Snapshot
Insert at End of Doubly Linked List:
- Create new node with data
- If list empty (head is None), set head = new node
- Else traverse to last node
- Set last.next = new node
- Set new_node.prev = last node
- New node's next = None
- List size increases by 1
Full Transcript
To insert a node at the end of a doubly linked list, first create the new node with the given data. Check if the list is empty by seeing if head is None. If empty, set head to the new node. Otherwise, start at head and move through the list until reaching the last node (where next is None). Then set the last node's next pointer to the new node, and set the new node's prev pointer back to the last node. The new node's next pointer is None, marking it as the new tail. This maintains the doubly linked structure with forward and backward links.