Bird
Raised Fist0
DSA Cprogramming~10 mins

Delete from End of Doubly Linked List in DSA C - Execution Trace

Choose your learning style10 modes available
Concept Flow - Delete from End of Doubly Linked List
Start at tail node
↓
Is tail null?
Yes→List empty, nothing to delete
No↓
Move tail to tail.prev
↓
Set new tail.next to null
↓
Delete old tail node
↓
Done
Start from the tail node, check if list is empty, move tail pointer back, update links, and delete the last node.
Execution Sample
DSA C
void deleteFromEnd(Node** head, Node** tail) {
    if (*tail == NULL) return;
    Node* toDelete = *tail;
    *tail = (*tail)->prev;
    if (*tail) (*tail)->next = NULL;
    else *head = NULL;
    free(toDelete);
}
Deletes the last node from a doubly linked list by updating tail and head pointers and freeing memory.
Execution Table
StepOperationNodes in ListPointer ChangesVisual State
1Start with list 10 <-> 20 <-> 30 (tail=30)10 <-> 20 <-> 30head → 10, tail → 30┌────────┐ ┌────────┐ ┌────────┐ │ data:10│ │ data:20│ │ data:30│ │ prev:∅ │←── │ prev:10│←── │ prev:20│ │ next:20│──→ │ next:30│──→ │ next:∅ │ └────────┘ └────────┘ └────────┘ head tail
2Check if tail is NULL (No)10 <-> 20 <-> 30No pointer changeSame as step 1
3Set toDelete = tail (30)10 <-> 20 <-> 30toDelete → 30Same as step 1
4Move tail to tail.prev (20)10 <-> 20 <-> 30tail: 30 → 20┌────────┐ ┌────────┐ ┌────────┐ │ data:10│ │ data:20│ │ data:30│ │ prev:∅ │←── │ prev:10│←── │ prev:20│ │ next:20│──→ │ next:30│──→ │ next:∅ │ └────────┘ └────────┘ └────────┘ head tail (moved) toDelete
5Set tail.next = NULL10 <-> 2020.next: 30 → NULL┌────────┐ ┌────────┐ ┌────────┐ │ data:10│ │ data:20│ │ data:30│ │ prev:∅ │←── │ prev:10│←── │ prev:20│ │ next:20│──→ │ next:∅ │ │ next:∅ │ └────────┘ └────────┘ └────────┘ head tail toDelete
6Free toDelete (30)10 <-> 20toDelete removed┌────────┐ ┌────────┐ │ data:10│ │ data:20│ │ prev:∅ │←── │ prev:10│ │ next:20│──→ │ next:∅ │ └────────┘ └────────┘ head tail
7Done10 <-> 20head → 10, tail → 20Final list after deletion
💡 Deletion complete; tail updated and last node removed
Variable Tracker
VariableStartAfter Step 3After Step 4After Step 5After Step 6Final
head101010101010
tail303020202020
toDeleteNULL303030NULLNULL
Key Moments - 3 Insights
Why do we move tail to tail.prev before deleting the node?
Because we need to update the tail pointer to the new last node before removing the old tail. See step 4 in execution_table where tail moves from 30 to 20.
What happens if the list has only one node?
After deletion, both head and tail become NULL. This is handled in the code by setting head to NULL if tail becomes NULL (not shown in this example but important).
Why do we set tail.next to NULL after moving tail?
To disconnect the new tail from the deleted node, ensuring the list ends properly. See step 5 where 20.next changes from 30 to NULL.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 4, what is the new value of tail?
ANode with data 30
BNode with data 20
CNULL
DNode with data 10
💡 Hint
Check the 'Pointer Changes' column at step 4 in execution_table
At which step does the tail's next pointer become NULL?
AStep 6
BStep 3
CStep 5
DStep 2
💡 Hint
Look at the 'Operation' and 'Pointer Changes' columns in execution_table
If the list had only one node, what would happen to head after deletion?
AIt becomes NULL
BIt points to tail
CIt remains pointing to the deleted node
DIt points to itself
💡 Hint
Refer to key_moments about single node list behavior
Concept Snapshot
Delete from End of Doubly Linked List:
- Start at tail node
- If tail is NULL, list is empty
- Move tail pointer to tail.prev
- Set new tail.next to NULL
- Free old tail node
- Update head to NULL if list becomes empty
Full Transcript
To delete the last node from a doubly linked list, we start at the tail node. If the tail is NULL, the list is empty and nothing is done. Otherwise, we save the tail node to delete, move the tail pointer back to the previous node, set the new tail's next pointer to NULL to disconnect the old tail, then free the old tail node. If the list had only one node, after deletion both head and tail become NULL. This process ensures the list remains properly linked and updated after deletion.

Practice

(1/5)
1. What happens to the tail pointer when you delete the last node from a doubly linked list?
easy
A. It becomes NULL immediately without checking.
B. It remains unchanged.
C. It points to the head node.
D. It moves to the previous node of the deleted node.

Solution

  1. Step 1: Understand the tail pointer role

    The tail pointer always points to the last node in the doubly linked list.
  2. Step 2: Update tail after deletion

    When the last node is deleted, the tail pointer must move to the previous node to keep pointing to the new last node.
  3. Final Answer:

    It moves to the previous node of the deleted node. -> Option D
  4. Quick Check:

    Tail points to previous node after deletion [OK]
Hint: Tail always points to last node; update to previous on delete [OK]
Common Mistakes:
  • Setting tail to NULL without checking if list is empty
  • Not updating tail pointer after deletion
  • Pointing tail to head incorrectly
2. Which of the following is the correct syntax to delete the last node in a doubly linked list in C?
easy
A. tail = tail->prev; free(tail->next); tail->next = NULL;
B. free(tail); tail = tail->prev; tail->next = NULL;
C. tail->prev = tail; free(tail); tail = NULL;
D. tail->next = NULL; free(tail); tail = tail->prev;

Solution

  1. Step 1: Free the last node correctly

    We first move tail to previous node, then free the old last node which is tail->next.
  2. Step 2: Update tail's next pointer

    After freeing, set tail->next to NULL to mark new end of list.
  3. Final Answer:

    tail = tail->prev; free(tail->next); tail->next = NULL; -> Option A
  4. Quick Check:

    Move tail first, free old node, update next pointer [OK]
Hint: Move tail first, then free old node, update next pointer [OK]
Common Mistakes:
  • Freeing tail before moving pointer
  • Not setting tail->next to NULL
  • Incorrect pointer assignments causing memory errors
3. What will be the output of the following code snippet after deleting the last node?
typedef struct Node {
  int data;
  struct Node* prev;
  struct Node* next;
} Node;

Node* tail = NULL;
// List: 10 <-> 20 <-> 30
// tail points to node with data 30

// Delete last node
Node* temp = tail;
tail = tail->prev;
free(temp);
tail->next = NULL;

// Print list from head
Node* head = tail;
while(head->prev) head = head->prev;
while(head) {
  printf("%d ", head->data);
  head = head->next;
}
medium
A. 10 20
B. 10 20 30
C. 20 30
D. 10 30

Solution

  1. Step 1: Understand list before deletion

    Initial list is 10 <-> 20 <-> 30, tail points to 30.
  2. Step 2: Delete last node and update pointers

    Last node 30 is freed, tail moves to 20, tail->next set to NULL.
  3. Step 3: Print list from head

    Head is found by moving to start (10), printing nodes 10 and 20.
  4. Final Answer:

    10 20 -> Option A
  5. Quick Check:

    Last node removed, list prints 10 20 [OK]
Hint: After deletion, tail moves back; print from head to see updated list [OK]
Common Mistakes:
  • Printing old tail node after deletion
  • Not updating tail->next to NULL
  • Starting print from tail instead of head
4. Identify the error in the following code snippet that deletes the last node of a doubly linked list:
void deleteEnd(Node** tail) {
  if (*tail == NULL) return;
  Node* temp = *tail;
  *tail = (*tail)->prev;
  free(temp);
  (*tail)->next = NULL;
}
medium
A. Not freeing the node properly.
B. Dereferencing tail without checking if list becomes empty.
C. Not updating the head pointer.
D. Using double pointer for tail unnecessarily.

Solution

  1. Step 1: Check for empty list after deletion

    If the list had only one node, after deletion tail becomes NULL, so (*tail)->next causes error.
  2. Step 2: Fix by checking tail before dereference

    Must check if *tail is not NULL before setting (*tail)->next = NULL.
  3. Final Answer:

    Dereferencing tail without checking if list becomes empty. -> Option B
  4. Quick Check:

    Check tail NULL before accessing next pointer [OK]
Hint: Always check if tail is NULL before accessing its members [OK]
Common Mistakes:
  • Dereferencing NULL pointer after deletion
  • Ignoring empty list edge case
  • Not freeing memory causing leaks
5. You have a doubly linked list with nodes: 5 <-> 15 <-> 25 <-> 35. After deleting the last node twice, what will be the printed list from head?
// Initial tail points to 35
// Delete last node twice
Node* temp;
temp = tail;
tail = tail->prev;
free(temp);
tail->next = NULL;

temp = tail;
tail = tail->prev;
free(temp);
tail->next = NULL;

// Print from head
Node* head = tail;
while(head->prev) head = head->prev;
while(head) {
  printf("%d ", head->data);
  head = head->next;
}
hard
A. 5 15 25
B. 15 25
C. 5 15
D. 25 35

Solution

  1. Step 1: Understand initial list and tail

    List is 5 <-> 15 <-> 25 <-> 35, tail points to 35.
  2. Step 2: Delete last node once

    Delete 35, tail moves to 25, tail->next = NULL.
  3. Step 3: Delete last node second time

    Delete 25, tail moves to 15, tail->next = NULL.
  4. Step 4: Print list from head

    Head found by moving to start (5), print nodes 5 and 15.
  5. Final Answer:

    5 15 -> Option C
  6. Quick Check:

    Two deletions remove last two nodes, list prints 5 15 [OK]
Hint: Each delete moves tail back; print from head to see current list [OK]
Common Mistakes:
  • Not updating tail->next to NULL after each deletion
  • Printing from tail instead of head
  • Assuming deleted nodes still exist
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard