Introduction
Hello! In our last lesson, we explored the queue data structure, its FIFO (First-In, First-Out) principle, and how to implement it efficiently in Python using collections.deque. We briefly mentioned that deque is built on a data structure called a "doubly linked list." Today, we're going to pull back the curtain and learn how to build a similar structure from the ground up.
Your learning outcome for this lesson is to define a Node class and implement a basic singly linked list.
Unlike Python's built-in lists, which store data in a single, contiguous block of memory, a linked list is a chain of individual objects scattered throughout memory, connected by pointers. Understanding this structure is crucial because it's a foundational concept in computer science, forms the basis for many other complex data structures, and is a very common topic in technical interviews.
1. The Core Concept of a Linked List
Imagine a scavenger hunt. Each clue you find doesn't just give you a piece of the puzzle; it also tells you where to find the next clue. A linked list works in a very similar way. It's a sequence of elements called nodes. Each node contains two things:
- The actual data (like a number, a string, etc.).
- A reference (or "pointer") to the next node in the sequence.
This chain has to start somewhere, so we always keep track of the very first node, which we call the head. The chain also has to end; the last node's "next" pointer simply points to None.
.webp)
This structure is fundamentally different from a Python list, which is implemented as a dynamic array. In an array, all elements are stored side-by-side in a continuous block of memory. In a linked list, the nodes can be located anywhere in memory, linked together only by their pointers.
2. The Building Block: The Node Class
To build a linked list, we must first define a blueprint for a single node. In Python, we do this by creating a class. Since you're familiar with classes from Module 3, this should be a straightforward step.
This first video will show you how to define the Node class.
2 Simple Ways To Code Linked Lists In Python
The video '2 Simple Ways To Code Linked Lists In Python' by Anthony Sistilli starts by explaining and implementing the node, which is the fundamental component of our linked list.
Watch from 00:20 to 01:38. The video explains the two attributes of a node (value and next) and shows how to create a LinkedListNode class in Python.
As you saw, the Node class is simple. It only needs a constructor (__init__) to set its initial state. Here is a clean implementation. Note that the video called the next attribute next_node to avoid a conflict with a Python keyword, which is good practice. We'll use next for simplicity, as it's a common convention and doesn't cause issues in this context.
class Node:
"""
An object for storing a single node of a linked list.
Models two attributes: data and the link to the next node.
"""
def __init__(self, data):
self.data = data # The data stored in the node (e.g., a number, string, etc.)
self.next = None # The reference to the next node in the list
When we create a Node, we pass it some data. Its next attribute is automatically set to None. This is because a newly created node doesn't point to anything yet; it's an isolated element until we explicitly link it to another node.
3. Creating a Basic Linked List
Now that we have our Node blueprint, we can create instances of it and link them together to form a chain. The following segment of the video demonstrates how to do this manually.
2 Simple Ways To Code Linked Lists In Python
Let's continue with the same video to see how these individual nodes are connected to form a basic linked list.
Watch from 01:38 to 05:27. Pay close attention to how the .next_node attribute of one node is assigned to another node object to create the links. Also, notice the while loop used to traverse and print the list.
This manual process is key to understanding how linked lists work. Let's write the code for it ourselves:
- Create individual nodes: We'll instantiate our
Nodeclass for each element we want in our list. - Link the nodes: We'll connect them by setting the
.nextattribute of each node. - Traverse the list: We'll start at the
headand follow the.nextpointers until we reachNone.
# 1. Create individual nodes
node1 = Node(3)
node2 = Node(7)
node3 = Node(10)
# At this point, we have three separate Node objects.
# node1.next is None
# node2.next is None
# node3.next is None
# 2. Link the nodes together
print("Linking nodes...")
node1.next = node2 # The node containing 3 now points to the node containing 7
node2.next = node3 # The node containing 7 now points to the node containing 10
# node3.next remains None, marking the end of the list.
# The first node, node1, is now the head of our list.
head = node1
# 3. Traverse and print the list
print("Traversing the list:")
current_node = head
while current_node is not None:
print(current_node.data, end=" -> ")
current_node = current_node.next # Move to the next node
print("None")
Running this code will produce the output:3 -> 7 -> 10 -> None
This confirms we have successfully created a basic linked list!
4. Encapsulating Logic with a LinkedList Class
While creating nodes and linking them manually is great for learning, it's not a practical way to manage a list. A much better approach is to create a LinkedList class that encapsulates the logic. This "manager" class will hold a reference to the head of the list and will eventually contain methods for adding, removing, and finding nodes.
For this lesson, we will create a LinkedList class that only does two things:
- Initializes an empty list (meaning its
headisNone). - Provides a method to print all the elements in the list.
This approach aligns with the object-oriented principles you've learned, hiding the internal details from the user.
Linked list python implementation and operations guide
To see how to define the Node and LinkedList classes, let's look at this article from Purple Tutor. It provides clean, simple code examples.
Please read the section titled 'Node class implementation in Python'. It provides a concise code snippet for the Node class, which is the essential building block.
Building on that, here is the combined code for both our Node and LinkedList classes.
class Node:
"""An object for storing a single node of a linked list."""
def __init__(self, data):
self.data = data
self.next = None
def __repr__(self):
# A helpful representation for printing a node
return f"Node({self.data})"
class LinkedList:
"""Manages the linked list, starting with the head."""
def __init__(self):
self.head = None # An empty list has no head
def print_list(self):
"""Traverses the list and prints the data of each node."""
current = self.head
while current:
print(current.data, end=" -> ")
current = current.next
print("None")
The __repr__ method in the Node class is a special method that provides a developer-friendly string representation of the object, which can be useful for debugging.
5. Your Turn: Practice Building a List
Now, let's use our new LinkedList class. Your task is to re-create the 3 -> 7 -> 10 list, but this time using the LinkedList class to manage it.
Instructions:
- Create an instance of the
LinkedListclass. - Create three
Nodeinstances with data3,7, and10. - Manually link the nodes together as we did before.
- Set the
headof yourLinkedListinstance to be the first node. - Call the
print_list()method on yourLinkedListinstance to display the result.
You can write your code below to test your understanding.
# Your code here
# 1. Create a LinkedList instance
my_list = LinkedList()
# 2. Create the nodes
node_a = Node(3)
node_b = Node(7)
node_c = Node(10)
# 3. Link the nodes
node_a.next = node_b
node_b.next = node_c
# 4. Set the head of the list
my_list.head = node_a
# 5. Print the list
print("My linked list:")
my_list.print_list()
# Expected output:
# My linked list:
# 3 -> 7 -> 10 -> None
This exercise demonstrates the relationship between the container (LinkedList) and its contents (Node objects).
Conclusion
Well done! You have successfully built a singly linked list from scratch, starting with its most basic component. This is a significant step in your journey to mastering data structures.
Key Takeaways:
- A linked list is a linear data structure made of nodes connected by pointers.
- A Node has two primary attributes:
dataand anextpointer to the subsequent node. - The start of the list is marked by the head, and the end is marked by a node whose
nextpointer isNone. - We can encapsulate the list's logic within a
LinkedListclass, which holds a reference to theheadnode. - Traversal is the process of visiting each node by following the
nextpointers, starting from thehead.
Preview of the Next Lesson:
Manually linking nodes is insightful, but not practical for real applications. In our next lesson, we will make our LinkedList class much more powerful. You will learn to implement insertion and deletion operations, allowing you to add and remove nodes from the list programmatically.