Doubly Linked List
Published: 2022-05-22 13:06:49

This is how it is different than singly linked list
_Singly Linked List_
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zl6xajvl12qqw5e1sml.png)
 
Doubly Linked List
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kmsnbq9lk4vuk2qbbdvr.png)

So, when creating a node in Singly Linked List, we had this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cp6nhggmbn6rshh5creb.png)
We actually had

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tumyz7lze32ghjeqq20g.png)
Which we wrote in class as this:

B![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9yxr6r49fav5g9nw8c04.png)
But the doubly Linked List, we will have :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cq5tbs0v5m0i4351te4t.png)

Now, lets create Doubly Linked List class
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pyndwhfr1iyupc3hiooe.png)
We will create the Doubly Linked List calling the class:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8co234xkn2w8olxomedb.png)
This makes a doubly Linked List:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z41lkc3dcddz5b68ak4w.png)

the whole code:

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

class DoublyLinkedList:
    def __init__(self, value):
        new_node = Node(value)
        self.head = new_node
        self.tail = new_node
        self.length = 1

    def print_list(self):
        temp = self.head
        while temp is not None:
            print(temp.value)
            temp = temp.next
  
#Creating a doubly Linked List which has a node 7
my_doubly_linked_list = DoublyLinkedList(7)

#Printing the list
my_doubly_linked_list.print_list()

```
   
    
 **_Append_**
Case 1:
When there is no value and adding one

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ujpcnsw3gz4lbnd07kdu.png)

 and make this to this

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nifob1gg4c29ea5mh7f3.png)
We will first check if head is point to None:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x5v6fbnqplxfnkbv2xvb.png)
Will make it 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ews067unjfvixto9wz0.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dbf61qacwbm7fr6dcy66.png)
Case 2:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nxrdiogv669m1k9hwttu.png)
Now we will code this to append a new node

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l0mjibklqxc4tf92myzw.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/44uch06olz905xmny1p4.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3hcjt8r5uqflr4tu7xoj.png)
So, the total code is:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/heqhz2e7x4x88upf3176.png)
 The total code:

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

class DoublyLinkedList:
    def __init__(self, value):
        new_node = Node(value)
        self.head = new_node
        self.tail = new_node
        self.length = 1

    def print_list(self):
        temp = self.head
        while temp is not None:
            print(temp.value)
            temp = temp.next
        
    def append(self, value):
        new_node = Node(value)
        if self.head is None:
            self.head = new_node
            self.tail = new_node
        else:
            self.tail.next = new_node
            new_node.prev = self.tail
            self.tail = new_node
        self.length += 1
        return True
  
#A linked list of a node 1
my_doubly_linked_list = DoublyLinkedList(1)
#Appending node 2
my_doubly_linked_list.append(2)

my_doubly_linked_list.print_list()


```
 


**_Pop_**    
Case 1:
If the List has 0 nodes

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/89d0uwfulb4flgvpelel.png)
For this , we will have:
Because we won't return anything
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6e951k3wbkmjwpxx53gc.png)
       
Case 2: If we have more than 2 value

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ttya8q88o5gh65eyjd3.png)
First we will create a temp variable

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ibmzez0dlpjvspukski.png)
Then we will set tail to the previous node:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s5sbicxcr0urb27sa6yc.png)
Then we will set the tail's next direction to None to break if from the last item:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v5vzi2608h2t4awtv6sa.png)
same for the last node:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67yc3jfj8sv26dkdgoqj.png)
 
Case 3:
When we have just  1 value:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n1d7hssw3280l8gbi1kb.png)
 
We will pop it and also set the head and tail to None:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fug7ot720jg5bw8uajoa.png)
 
The list will be something like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eymos1qqyoahyprfsryy.png)

So, the code will look like this:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gr9g8ta20a5xgyol4uh5.png)

Also , we can change it to this format:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o0qsruar3g0jojk5evsu.png)
Total code:

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

class DoublyLinkedList:
    def __init__(self, value):
        new_node = Node(value)
        self.head = new_node
        self.tail = new_node
        self.length = 1

    def print_list(self):
        temp = self.head
        while temp is not None:
            print(temp.value)
            temp = temp.next
        
    def append(self, value):
        new_node = Node(value)
        if self.head is None:
            self.head = new_node
            self.tail = new_node
        else:
            self.tail.next = new_node
            new_node.prev = self.tail
            self.tail = new_node
        self.length += 1
        return True

    def pop(self):
        #For 0 items in list
        if self.length == 0:
            return None
        temp = self.tail
        #For 1 items in list
        if self.length == 1:
            self.head = None
            self.tail = None 
        #For more than 1 nodes in list
        else:       
            self.tail = self.tail.prev
            self.tail.next = None
            temp.prev = None
        self.length -= 1
        return temp
  
#Creates a list of Node 1 & Node 2

my_doubly_linked_list = DoublyLinkedList(1)
my_doubly_linked_list.append(2)


# (2) Items - Returns  Node 2
print(my_doubly_linked_list.pop())
# (1) Item -  Returns  Node 1
print(my_doubly_linked_list.pop())
# (0) Items - Returns  None
print(my_doubly_linked_list.pop())


```

**_Prepend_**      
Case: 1
When we have nothing in the list

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qfxn1webm1vcuvjwm9s5.png)
So, we will set the head & tail to it:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2i76siqjhrisz0rnqeu.png)
Case 2:
if we have more than 1 values:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jai6nn4w1wn7jm46g0y7.png)
We will first do this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wyseespdsj8vb80aguso.png)
then

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u8cj024kq5cny9w0i1g5.png)
then

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m6s16s7gh69718jltnkj.png)

Total code becomes:

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

class DoublyLinkedList:
    def __init__(self, value):
        new_node = Node(value)
        self.head = new_node
        self.tail = new_node
        self.length = 1

    def print_list(self):
        temp = self.head
        while temp is not None:
            print(temp.value)
            temp = temp.next
        
    def append(self, value):
        new_node = Node(value)
        if self.head is None:
            self.head = new_node
            self.tail = new_node
        else:
            self.tail.next = new_node
            new_node.prev = self.tail
            self.tail = new_node
        self.length += 1
        return True

    def pop(self):
        if self.length == 0:
            return None
        temp = self.tail
        if self.length == 1:
            self.head = None
            self.tail = None 
        else:       
            self.tail = self.tail.prev
            self.tail.next = None
            temp.prev = None
        self.length -= 1
        return temp

    def prepend(self, value):
        new_node = Node(value)
        # If we have no value in the list
        if self.length == 0:
            self.head = new_node
            self.tail = new_node
        #If we have more than 1 values
        else:
            new_node.next = self.head
            self.head.prev = new_node
            self.head = new_node
        self.length += 1
        return True

#Doubly list with Node 1 & Node 3
my_doubly_linked_list = DoublyLinkedList(2)
my_doubly_linked_list.append(3)

#Prepending Node 1
my_doubly_linked_list.prepend(1)

my_doubly_linked_list.print_list()
```
**_Get_**
For the Singly Linked List we had this code right:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i2lm1t1hzt7lthaqqzm8.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y1xvdksa753sq9ifuue3.png)

We will then turn this to this

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dgp1lupateshxcn89d8p.png)

Case 1:
Let's return something that is within the Doubly Linked List. Let's return index 1

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jfz960buuwz95zpsk9tm.png)
If the index is in 1st half

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7kfngik5fcrxzbu5nlp.png)
if on 2nd half

S![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p2fa34zk6dbxndgs3qrb.png)
setting tail as temp and iterate backward 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6pswmqx93ke3mzu0kg7.png)
and return the temp when we get that

So, the total code will be 

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

class DoublyLinkedList:
    def __init__(self, value):
        new_node = Node(value)
        self.head = new_node
        self.tail = new_node
        self.length = 1

    def print_list(self):
        temp = self.head
        while temp is not None:
            print(temp.value)
            temp = temp.next
        
    def append(self, value):
        new_node = Node(value)
        if self.head is None:
            self.head = new_node
            self.tail = new_node
        else:
            self.tail.next = new_node
            new_node.prev = self.tail
            self.tail = new_node
        self.length += 1
        return True

    def pop(self):
        if self.length == 0:
            return None
        temp = self.tail
        if self.length == 1:
            self.head = None
            self.tail = None 
        else:       
            self.tail = self.tail.prev
            self.tail.next = None
            temp.prev = None
        self.length -= 1
        return temp

    def prepend(self, value):
        new_node = Node(value)
        if self.length == 0:
            self.head = new_node
            self.tail = new_node
        else:
            new_node.next = self.head
            self.head.prev = new_node
            self.head = new_node
        self.length += 1
        return True

    def pop_first(self):
        if self.length == 0:
            return None
        temp = self.head
        if self.length == 1:
            self.head = None
            self.tail = None
        else:
            self.head = self.head.next
            self.head.prev = None
            temp.next = None      
        self.length -= 1
        return temp

    def get(self, index):
        if index < 0 or index >= self.length:
            return None
        temp = self.head
        #Checking if the index is in 1st half
        if index < self.length/2:
            for _ in range(index):
                temp = temp.next
        #Checking if the index is in 2nd half
        else:
            temp = self.tail
            for _ in range(self.length - 1, index, -1):
                temp = temp.prev  
        return temp #Will return the node . But for value, use temp.value
        
#Creating a doubly list of 0,5,9,3
my_doubly_linked_list = DoublyLinkedList(0)
my_doubly_linked_list.append(5)
my_doubly_linked_list.append(9)
my_doubly_linked_list.append(3)


#Lokking for index 1 no node
print(my_doubly_linked_list.get(1))

#Looking for index 2 no node
print(my_doubly_linked_list.get(2))

```

**_Set_**
Let's set this index 1 value from 3 to 4.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5ukzk4m6p9kp6km94x23.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jobu9115pbl7l7wbplzl.png)
so,here we are going to check if the index is within range and if so, then we will change the value

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pw6m3dtm9gp40c59n60m.png)
else will return False

The whole code is

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

class DoublyLinkedList:
    def __init__(self, value):
        new_node = Node(value)
        self.head = new_node
        self.tail = new_node
        self.length = 1

    def print_list(self):
        temp = self.head
        while temp is not None:
            print(temp.value)
            temp = temp.next
        
    def append(self, value):
        new_node = Node(value)
        if self.head is None:
            self.head = new_node
            self.tail = new_node
        else:
            self.tail.next = new_node
            new_node.prev = self.tail
            self.tail = new_node
        self.length += 1
        return True

    def pop(self):
        if self.length == 0:
            return None
        temp = self.tail
        if self.length == 1:
            self.head = None
            self.tail = None 
        else:       
            self.tail = self.tail.prev
            self.tail.next = None
            temp.prev = None
        self.length -= 1
        return temp

    def prepend(self, value):
        new_node = Node(value)
        if self.length == 0:
            self.head = new_node
            self.tail = new_node
        else:
            new_node.next = self.head
            self.head.prev = new_node
            self.head = new_node
        self.length += 1
        return True

    def pop_first(self):
        if self.length == 0:
            return None
        temp = self.head
        if self.length == 1:
            self.head = None
            self.tail = None
        else:
            self.head = self.head.next
            self.head.prev = None
            temp.next = None      
        self.length -= 1
        return temp

    def get(self, index):
        if index < 0 or index >= self.length:
            return None
        temp = self.head
        if index < self.length/2:
            for _ in range(index):
                temp = temp.next
        else:
            temp = self.tail
            for _ in range(self.length - 1, index, -1):
                temp = temp.prev  
        return temp
        
    def set_value(self, index, value):
        temp = self.get(index)
        #if the index is within the range
        if temp:
            temp.value = value
            return True
        #if the index is not within range    
        return False
    
#Doubly linked list of 11,3,23,7  
my_doubly_linked_list = DoublyLinkedList(11)
my_doubly_linked_list.append(3)
my_doubly_linked_list.append(23)
my_doubly_linked_list.append(7)


#setting index value to 4

my_doubly_linked_list.set_value(1,4)

my_doubly_linked_list.print_list()

```
   
**_Insert_**

At a particular index, we are going to insert a node.
Firstly, we are going to check if the index is within the range

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5bh9ao0oosv7pvdli994.png)
 
Case 1:
If needs to add it at the beginning

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0elyaky40a4s7djyvblz.png)

Case 2:
Adding it to the last of the list

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3b8769yjvgvff8xfd546.png)

case 3:
Adding in somewhere middle. 
Assume that we want to make this
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pkcxw9l3coyatv0s2nfb.png)    
to that

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1btmohv6auednqila15t.png)

so, trying to insert the node between 1 & 2. 
So, we will set index 1 to before and index 2 to after

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kdiceht66beede9b0ha3.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mjt0imsww0v601ze7dxv.png)

We are going to make this 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1r7kpfr0fsk612g2qeur.png)
to this


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/07macqvlmhphi55he9c5.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/agh63ifbjfl7d20z0tnc.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/szlw5aunmjx6u41ba1iw.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ztgu1kea097b8159fj47.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s0dzmgv86vtappa766z7.png)

So, the code is

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

class DoublyLinkedList:
    def __init__(self, value):
        new_node = Node(value)
        self.head = new_node
        self.tail = new_node
        self.length = 1

    def print_list(self):
        temp = self.head
        while temp is not None:
            print(temp.value)
            temp = temp.next
        
    def append(self, value):
        new_node = Node(value)
        if self.head is None:
            self.head = new_node
            self.tail = new_node
        else:
            self.tail.next = new_node
            new_node.prev = self.tail
            self.tail = new_node
        self.length += 1
        return True

    def pop(self):
        if self.length == 0:
            return None
        temp = self.tail
        if self.length == 1:
            self.head = None
            self.tail = None 
        else:       
            self.tail = self.tail.prev
            self.tail.next = None
            temp.prev = None
        self.length -= 1
        return temp

    def prepend(self, value):
        new_node = Node(value)
        if self.length == 0:
            self.head = new_node
            self.tail = new_node
        else:
            new_node.next = self.head
            self.head.prev = new_node
            self.head = new_node
        self.length += 1
        return True

    def pop_first(self):
        if self.length == 0:
            return None
        temp = self.head
        if self.length == 1:
            self.head = None
            self.tail = None
        else:
            self.head = self.head.next
            self.head.prev = None
            temp.next = None      
        self.length -= 1
        return temp

    def get(self, index):
        if index < 0 or index >= self.length:
            return None
        temp = self.head
        if index < self.length/2:
            for _ in range(index):
                temp = temp.next
        else:
            temp = self.tail
            for _ in range(self.length - 1, index, -1):
                temp = temp.prev  
        return temp
        
    def set_value(self, index, value):
        temp = self.get(index)
        if temp:
            temp.value = value
            return True
        return False
    
    def insert(self, index, value):
        #to check if the index is within range
        if index < 0 or index > self.length:
            return False
        #to add a node at the start
        if index == 0:
            return self.prepend(value)
        #to add a node at the end    
        if index == self.length:
            return self.append(value)
        #to add a node within the list
        new_node = Node(value)
        before = self.get(index - 1)
        after = before.next

        new_node.prev = before
        new_node.next = after
        before.next = new_node
        after.prev = new_node
        
        self.length += 1   
        return True  

  
#Doubly linked list of nodes 1 ,3
my_doubly_linked_list = DoublyLinkedList(1)
my_doubly_linked_list.append(3)



#at the index 1, adding node 2
my_doubly_linked_list.insert(1,2)

my_doubly_linked_list.print_list()

```

**_Remove_**

Checking if the index is out of range

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z3upvswfyamboyqqv03s.png)
Case 1:
Returning the first item.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5dxku7axia5mogg0o36r.png)
this to this

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qszq5fgcn7dlxpnxxhwu.png)
For this, we will just pop

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yz9cymu6mlmep43ni3bu.png)
 Case 2:
To remove from last.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/snd5focnyso0r91prdiv.png)
Case 3:
To remove something from middle

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8a8yohnakrz4io5fpbmp.png)
For example, we will remove the index 2 number value. Firstly, pointing a variable to it

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ml6b77iwe4n1i8ue5kgy.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wd7xdk8qzu426xvanxyi.png)
Which can be something like this

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2effixglfuknoa3sxx5l.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uo3ra60dqhakuul75m5f.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wkjpszj42vhwjjo47peg.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gjhu1inctjjtjup0h70w.png)
using

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pjj5hvjrgrtv12b7geu0.png)


Total code will be

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

class DoublyLinkedList:
    def __init__(self, value):
        new_node = Node(value)
        self.head = new_node
        self.tail = new_node
        self.length = 1

    def print_list(self):
        temp = self.head
        while temp is not None:
            print(temp.value)
            temp = temp.next
        
    def append(self, value):
        new_node = Node(value)
        if self.head is None:
            self.head = new_node
            self.tail = new_node
        else:
            self.tail.next = new_node
            new_node.prev = self.tail
            self.tail = new_node
        self.length += 1
        return True

    def pop(self):
        if self.length == 0:
            return None
        temp = self.tail
        if self.length == 1:
            self.head = None
            self.tail = None 
        else:       
            self.tail = self.tail.prev
            self.tail.next = None
            temp.prev = None
        self.length -= 1
        return temp

    def prepend(self, value):
        new_node = Node(value)
        if self.length == 0:
            self.head = new_node
            self.tail = new_node
        else:
            new_node.next = self.head
            self.head.prev = new_node
            self.head = new_node
        self.length += 1
        return True

    def pop_first(self):
        if self.length == 0:
            return None
        temp = self.head
        if self.length == 1:
            self.head = None
            self.tail = None
        else:
            self.head = self.head.next
            self.head.prev = None
            temp.next = None      
        self.length -= 1
        return temp

    def get(self, index):
        if index < 0 or index >= self.length:
            return None
        temp = self.head
        if index < self.length/2:
            for _ in range(index):
                temp = temp.next
        else:
            temp = self.tail
            for _ in range(self.length - 1, index, -1):
                temp = temp.prev  
        return temp
        
    def set_value(self, index, value):
        temp = self.get(index)
        if temp:
            temp.value = value
            return True
        return False
    
    def insert(self, index, value):
        if index < 0 or index > self.length:
            return False
        if index == 0:
            return self.prepend(value)
        if index == self.length:
            return self.append(value)

        new_node = Node(value)
        before = self.get(index - 1)
        after = before.next

        new_node.prev = before
        new_node.next = after
        before.next = new_node
        after.prev = new_node
        
        self.length += 1   
        return True  

    def remove(self, index):
        #Checking the range
        if index < 0 or index >= self.length:
            return None
        #to remove from the beginning    
        if index == 0:
            return self.pop_first()
        #to remove from the last    
        if index == self.length - 1:
            return self.pop()
        
        #to remove from the middle of the doubly linked list
        temp = self.get(index)
        
        temp.next.prev = temp.prev
        temp.prev.next = temp.next
        temp.next = None
        temp.prev = None

        self.length -= 1
        return temp
  
# a doubly linked list of 0,1 & 2 nodes
my_doubly_linked_list = DoublyLinkedList(0)
my_doubly_linked_list.append(1)
my_doubly_linked_list.append(2)


# removing index 1 out of the list
print(my_doubly_linked_list.remove(1), '\n')

my_doubly_linked_list.print_list()
```

Done!

<img src="https://c.tenor.com/Tvd3VKwtse0AAAAC/cat-cute.gif">