Adventures in Machine Learning

Double the Efficiency: the Power of Deque in Python

Efficiency of deque over list for append and pop operations:

The insertion and deletion (Add and Remove) operation efficiency is the prime reason to use Deque over List. The List structure performs poorly while adding/deleting elements to/from its beginning or end.

Deque inserts and deletes elements from its head and tail ends, and the average time complexity is O(1), which means the operations take constant time, which is independent of the number of elements present in Deque. On the other hand, with List, adding an element at the beginning or end requires you to reassign new index values to existing elements, making it inefficient.

Therefore, Deque is more appropriate for these operations. Implementation of deque as a doubly linked list and its usefulness for stacks and queues:

Deque can be implemented using a doubly linked list, where every node contains the current item, a reference (pointer) to the next node, and a reference (pointer) to the previous node.

The doubly linked list provides efficient access and manipulation of elements; it allows insertion, deletion, and traversal in both directions. Deque has many use cases in computer science, but the two most prominent are Stacks and Queues.

In the stack implementation, the last element added, is the first one to be removed. Therefore, Deque operating from the head (front) end, acts as a Stack, adding/removing from the same end.

On the other hand, while implementing Queues, Deque operates by adding elements to the tail (rear) end and removing/dequeueing the elements from the head end of Deque.

Example of using deque for implementing a queue:

Deque proves to be an efficient data structure for implementing a Queue, where data needs to be added and removed in FIFO order (First-In/First-Out).

We will see an example of implementing enqueue and dequeue operations via a Deque data structure.

Enqueue Operation:

New elements are added to the back of the queue, i.e., tail of Deque data structure.

This operation is called “append” in the Deque module.

Code:

from collections import deque
# Creating an empty Deque
queue = deque()
queue.append(2)
queue.append(6)
queue.append(1)
print(queue) # deque([2, 6, 1])

Dequeue Operation:

Elements are removed from the front side of the Deque because they represent the first element of our queue. This operation is called “popleft” in the Deque module.

Code:

from collections import deque
# Creating a Deque
queue = deque([2, 6, 1])
queue.popleft()
print(queue) # deque([6,1])

Conclusion:

In conclusion, Deque is a versatile and efficient data structure that allows effective manipulation of elements from both ends. Its implementation as a doubly linked list provides fast access and manipulation of elements, making it an ideal choice for implementing stacks and queues.

We saw how Deque can be implemented as a queue, using the FIFO approach, where new elements are added to the back and removed from the front of the data structure. Finally, Deque can be used in other applications, such as implementing the Railway reservation system, scheduling tasks, and even for analyzing financial data.

Its usage primarily depends on the requirements of the implementation.

Initializing and using deque for various purposes:

Deques can be initialized with optional arguments, such as an iterable or a maximum length (maxlen).

An iterable is a sequence of elements, such as a list or a tuple, that can be passed to the deque constructor as an argument. The deque will then be initialized with the elements from the iterable.

Code:

from collections import deque
mylist = [1, 2, 3, 4]
mydeque = deque(mylist)
print(mydeque) # deque([1, 2, 3, 4])

The maxlen parameter is crucial in defining how large the deque can grow. Once the number of elements in the deque reaches the defined max length, the deque will automatically discard old items when new items are added.

Deque has an efficient method in-built to discard old items called as ‘blow off’. This feature is beneficial in situations where the queue needs to have a maximum capacity and cannot grow beyond it, avoiding over-consumption of memory.

Code:

from collections import deque
mydeque = deque(maxlen=5)
print(mydeque) # deque([])
mydeque.append(1)
mydeque.append(2)
mydeque.append(3)
mydeque.append(4)
mydeque.append(5)
print(mydeque) # deque([1, 2, 3, 4, 5], maxlen=5)
mydeque.append(6)
print(mydeque) # deque([2, 3, 4, 5, 6], maxlen=5)

In addition to append and pop operations, Deque supports many other operations. One of those operations is called “extend” and can add multiple items to deque in one go.

It takes an iterable as an argument and adds all the elements one-by-one to the deque from the iterable. Another method supported by Deque is “insert,” which allows for the insertion of an element between any two existing elements at a specific index.

Code:

from collections import deque
mydeque = deque([1, 2, 3])
mydeque.append(4)
print(mydeque) # deque([1, 2, 3, 4])
mydeque.extend([5, 6, 7])
print(mydeque) # deque([1, 2, 3, 4, 5, 6, 7])
mydeque.insert(2, 8)
print(mydeque) # deque([1, 2, 8, 3, 4, 5, 6, 7])

Rotating and accessing elements in deque:

Deque allows for the rotation of deque items using the rotate function. rotate accepts an integer as an argument, which specifies the number of rotations to be made.

Positive integers rotate deque to the right, while negative integers rotate deque to the left. During rotation, the last item is moved to the top or bottom, depending on the direction of rotation.

Code:

from collections import deque
mydeque = deque([1, 2, 3, 4, 5])
mydeque.rotate(2)
print(mydeque) # deque([4, 5, 1, 2, 3])
mydeque.rotate(-2)
print(mydeque) # deque([1, 2, 3, 4, 5])

Deque also provides indexing features, but it does not support slicing operations like other sequences like List. Indexing in Deque is possible using square brackets.

In Deque, indexing starts from zero for the first item on the left side, and -1 for the first item on the right side. Indexing and deletion at both ends of the deque is an O(1) operation, unlike slicing.

Code:

from collections import deque
mydeque = deque([1, 2, 3, 4, 5])
print(mydeque[0]) # 1
print(mydeque[-1]) # 5
del mydeque[0]
print(mydeque) # deque([2, 3, 4, 5])

Conclusion:

Deque is a versatile and efficient data structure that allows insertion and deletion of elements at both ends. It is implemented using a doubly linked list, providing easy access and manipulation of elements.

The Deque structure can be initialized with optional parameters like iterable and maxlen. Maxlen provides a maximum size for the Deque, and once the maximum size is reached, Deque deletes the old elements.

Deque has additional methods such as extending, inserting, and many more. In addition, Deque can be manipulated by the rotation function.

Deque provides an efficient way of indexing and deleting items from both ends. Using Deque can improve the efficiency of programs, which require a data structure that can perform add and remove operations at both ends.

In conclusion, Deque is a powerful and efficient data structure that is implemented using a doubly linked list. The primary reason for using the Deque data structure over List is its ability to add and remove elements efficiently at both ends.

Deque can initialize using optional arguments, such as iterable and maxlen, and has additional features like extending or inserting elements. The rotatable features and efficient indexing and deletion make Deque a versatile data structure that can be useful for many applications.

Overall, using Deque in Python can provide significant improvements in terms of program efficiency. By utilizing Deque’s versatility, developers can create powerful programs that are faster, efficient, and reliable.

Popular Posts