📖 Scenario: Imagine you are building a simple music playlist app. Each song in the playlist needs to be connected to the previous and next songs so users can easily move forward or backward.
🎯 Goal: You will create the basic building blocks of a doubly linked list by designing the Node class and the DoublyLinkedList class with methods to add nodes. This will help you understand how songs are linked in both directions.
📋 What You'll Learn
Create a Node class with data, prev, and next attributes
Create a DoublyLinkedList class with a head attribute initialized to None
Add a method append in DoublyLinkedList to add a new node at the end
Print the playlist forward showing each node's data connected by arrows
💡 Why This Matters
🌍 Real World
Doubly linked lists are used in music players, web browsers, and photo viewers to move back and forth between items easily.
💼 Career
Understanding doubly linked lists helps in software development roles that involve data structure design, memory management, and building efficient navigation systems.
Progress0 / 4 steps
1
Create the Node class
Create a class called Node with an __init__ method that takes a parameter data. Inside the method, set self.data = data, self.prev = None, and self.next = None.
DSA Python
Hint
Think of Node as a box that holds a song name and links to the previous and next songs.
2
Create the DoublyLinkedList class with head
Create a class called DoublyLinkedList with an __init__ method that sets self.head = None.
DSA Python
Hint
The DoublyLinkedList class will manage the playlist starting from the first song called head.
3
Add append method to add nodes at the end
Inside the DoublyLinkedList class, create a method called append that takes a parameter data. This method should create a new Node with data. If self.head is None, set self.head to the new node. Otherwise, traverse the list to the last node and link the new node after it by setting the last node's next to the new node and the new node's prev to the last node.
DSA Python
Hint
Think of adding a new song at the end of the playlist. You find the last song and link the new one after it.
4
Print the playlist forward
Create a method called print_forward inside the DoublyLinkedList class. This method should start from self.head and print each node's data followed by -> until the last node, then print None. After defining the class, create a DoublyLinkedList object called playlist, append the songs 'Song1', 'Song2', and 'Song3' to it, and call playlist.print_forward() to display the playlist.
DSA Python
Hint
Print each song followed by an arrow until you reach the end, then print None to show the playlist ends.
Practice
(1/5)
1. What is the main difference between a doubly linked list node and a singly linked list node?
easy
A. A doubly linked list node does not store any data.
B. A doubly linked list node has pointers to both the previous and next nodes.
C. A doubly linked list node can only point to the next node.
D. A doubly linked list node stores data in a different format.
Solution
Step 1: Understand node pointers in singly linked list
A singly linked list node has only one pointer to the next node.
Step 2: Understand node pointers in doubly linked list
A doubly linked list node has two pointers: one to the previous node and one to the next node.
Final Answer:
A doubly linked list node has pointers to both the previous and next nodes. -> Option B
Quick Check:
Doubly linked list nodes have two pointers = D [OK]
Hint: Remember: doubly means two pointers, singly means one [OK]
Common Mistakes:
Thinking doubly linked list nodes store data differently
Confusing pointer count between singly and doubly linked lists
Assuming doubly linked list nodes have only one pointer
2. Which of the following is the correct way to define a doubly linked list node class in Python?
easy
A. class Node:
def __init__(self, data):
self.data = data
self.next = None
B. class Node:
def __init__(self, data):
self.next = None
self.prev = None
C. class Node:
def __init__(self, data):
self.data = data
self.prev = None
D. class Node:
def __init__(self, data):
self.data = data
self.prev = None
self.next = None
Solution
Step 1: Check for data storage and pointers
A doubly linked list node must store data and have both prev and next pointers.
Step 2: Verify class definitions
class Node:
def __init__(self, data):
self.data = data
self.prev = None
self.next = None correctly defines data, prev, and next attributes in __init__.
Final Answer:
class Node:\n def __init__(self, data):\n self.data = data\n self.prev = None\n self.next = None -> Option D
Quick Check:
Node class with data, prev, next = B [OK]
Hint: Doubly linked nodes need both prev and next pointers [OK]
Common Mistakes:
Omitting the prev pointer
Not initializing data attribute
Defining only next pointer like singly linked list
3. What will be the output of the following code snippet?
class Node:
def __init__(self, data):
self.data = data
self.prev = None
self.next = None
head = Node(1)
second = Node(2)
third = Node(3)
head.next = second
second.prev = head
second.next = third
third.prev = second
current = third
result = []
while current:
result.append(current.data)
current = current.prev
print(result)
medium
A. [3, 2, 1]
B. [1, 2, 3]
C. [1, 3, 2]
D. [3, 1, 2]
Solution
Step 1: Understand the linked list connections
Nodes are linked as 1 <-> 2 <-> 3 with prev and next pointers set correctly.
Step 2: Trace the while loop starting from third node
Starting at node with data 3, append 3, move to prev (2), append 2, move to prev (1), append 1, then prev is None, loop ends.
Final Answer:
[3, 2, 1] -> Option A
Quick Check:
Traverse backward from third node = [3, 2, 1] [OK]
Hint: Backward traversal collects nodes in reverse order [OK]
Common Mistakes:
Confusing next and prev pointers during traversal
Starting traversal from head instead of third
Appending data in wrong order
4. Identify the error in the following doubly linked list node insertion code and select the correct fix.
class Node:
def __init__(self, data):
self.data = data
self.prev = None
self.next = None
head = Node(1)
new_node = Node(2)
# Insert new_node after head
new_node.next = head.next
head.next.prev = new_node
head.next = new_node
new_node.prev = head
medium
A. No error; code inserts node correctly.
B. new_node.prev should be assigned before head.next.
C. head.next.prev causes AttributeError; fix by checking if head.next is not None before accessing prev.
D. new_node.next should be assigned after head.next.
Solution
Step 1: Analyze head.next before insertion
Initially, head.next is None, so head.next.prev causes AttributeError.
Step 2: Fix by checking if head.next exists before accessing prev
Adding a condition to check if head.next is not None before setting head.next.prev avoids error.
Final Answer:
head.next.prev causes AttributeError; fix by checking if head.next is not None before accessing prev. -> Option C
Quick Check:
Check for None before accessing prev pointer [OK]
Hint: Always check if next node exists before accessing its prev [OK]
Common Mistakes:
Ignoring None check causing runtime error
Assigning pointers in wrong order
Assuming head.next is always valid
5. You want to insert a new node with value 4 between nodes with values 2 and 3 in a doubly linked list. Given the nodes are connected as 1 <-> 2 <-> 3, which sequence of pointer updates correctly inserts the new node?