Seth Barrett

Daily Blog Post: January 18th, 2023

Jan 18th, 2023

Implementing Doubly Linked Lists in Python
Python13

Hello fellow Python enthusiasts!

In this post, we will be continuing our exploration of advanced topics in Python by discussing doubly linked lists.

But first, let's start with a quick refresher on what a linked list is. A linked list is a linear data structure where each element is a separate object, linked together using pointers. Each element, or node, in a linked list consists of two fields: a data field to store the element, and a next field to store the reference to the next node in the list.

As we learned in our previous post on linked lists, there are two types of linked lists: singly linked lists and doubly linked lists. In a singly linked list, each node has a reference to the next node in the list, but not the previous one. In a doubly linked list, each node has a reference to both the next and previous nodes. This allows us to traverse the list in both directions, making doubly linked lists more flexible than singly linked lists.

Now that we have a basic understanding of doubly linked lists, let's see how we can implement them in Python.

We can start by modifying our Node class from our previous post on linked lists to include a reference to the previous node as well.

class Node:
    def __init__(self, data=None):
        self.data = data
        self.next = None
        self.prev = None

Next, we can create a DoublyLinkedList class to represent the doubly linked list itself. This class will have a head and tail instance variables to keep track of the first and last nodes in the list.

class DoublyLinkedList:
    def __init__(self):
        self.head = None
        self.tail = None 

We can then add various methods to the DoublyLinkedList class to manipulate the list. For example, we can add a method to add a new node to the list, a method to remove a node from the list, and a method to find a specific node in the list.

class DoublyLinkedList:
    def __init__(self):
        self.head = None
        self.tail = None
    
    def add_node(self, data):
        new_node = Node(data)
        if self.head is None:
            self.head = new_node
            self.tail = new_node
        else:
            new_node.prev = self.tail
            self.tail.next = new_node
            self.tail = new_node
    
    def remove_node(self, data):
        current_node = self.head
        while current_node:
            if current_node.data == data:
                if current_node.prev:
                    current_node.prev.next = current_node.next
                else:
                    self.head = current_node.next
                if current_node.next:
                    current_node.next.prev = current_node.prev
                else:
                    self.tail = current_node.prev
                return
            current_node = current_node.next
    
    def find_node(self, data):
        current_node = self.head
        while current_node:
            if current_node.data == data:
                return current_node
            current_node = current_node.next
        return None 

With these methods in place, we now have a basic implementation of a doubly linked list in Python.

It's worth noting that the methods we've implemented so far are for a basic doubly linked list, and there are many other methods and variations that can be added to a doubly linked list class. For example, we could add a method to insert a node at a specific position in the list, or a method to sort the list in a particular order.

I hope this has been a helpful introduction to doubly linked lists in Python. Happy coding!