pull/1282/head
mankalavaishnavi 2024-06-24 13:27:00 +05:30
rodzic 8ee6007bbf
commit fd466af7e0
1 zmienionych plików z 144 dodań i 84 usunięć

Wyświetl plik

@ -1,108 +1,168 @@
## Double-Ended Queue (Deque)
# Deque in Python
A double-ended queue (deque) supports insertion and deletion from both ends, making it a more versatile queue implementation.
## Definition
A deque, short for double-ended queue, is an ordered collection of items that allows rapid insertion and deletion at both ends.
### Input-Restricted Deque
## Syntax
In Python, deques are implemented in the collections module:
In an input-restricted deque, elements can only be inserted from one end while deletions can occur from both ends.
### Output-Restricted Deque
An output-restricted deque allows elements to be deleted from one end only, while insertions can be made from both ends.
## Real Life Examples of Deques
### Task Scheduling
Deques are useful in task scheduling algorithms where tasks can be added to either end and processed accordingly based on priority or other scheduling criteria.
### Sliding Window Problems
Algorithms solving sliding window problems often use deques to efficiently manage and query elements in the current window.
### Implementations in Python
Python provides a built-in `collections.deque` which supports efficient append and pop operations from both ends. It's ideal for scenarios requiring a simple and efficient double-ended queue.
## Operations on a Deque
- **isEmpty**: Checks if the deque is empty.
- **appendLeft**: Adds an element to the left end of the deque.
- **appendRight**: Adds an element to the right end of the deque.
- **popLeft**: Removes and returns the element from the left end of the deque.
- **popRight**: Removes and returns the element from the right end of the deque.
- **peekLeft**: Returns the element from the left end without removing it.
- **peekRight**: Returns the element from the right end without removing it.
- **clear**: Removes all elements from the deque.
## Implementation of Deque in Python
Python's `collections.deque` provides an efficient implementation of a deque.
```python
```py
from collections import deque
# Creating a deque
dq = deque()
# Adding elements to the deque
dq.append(1)
dq.append(2)
dq.append(3)
# Removing elements from the deque
dq.popleft() # Removes and returns 1
dq.pop() # Removes and returns 3
# Peeking elements
print("Left end peek:", dq[0])
print("Right end peek:", dq[-1])
# Displaying elements in the deque
print("Deque:", list(dq))
d = deque(iterable) # Create deque from iterable (optional)
```
## Example: Sliding Window Maximum
## Operations
1. **Appending Elements**:
In this example, we'll use a deque to efficiently find the maximum element in sliding windows of a list.
- append(x): Adds element x to the right end of the deque.
- appendleft(x): Adds element x to the left end of the deque.
```python
2. **Removing Elements**:
- pop(): Removes and returns the rightmost element.
- popleft(): Removes and returns the leftmost element.
3. **Accessing Elements**:
- deque[index]: Accesses element at index.
4. **Other Operations**:
- extend(iterable): Extends deque by appending elements from iterable.
- extendleft(iterable): Extends deque by appending elements from iterable to the left.
- rotate(n): Rotates deque n steps to the right (negative n rotates left).
## Example
### 1. showing all the operations
```py
from collections import deque
def sliding_window_maximum(nums, k):
# Initialize a deque
d = deque([1, 2, 3, 4, 5])
print("Initial deque:", d)
# Append elements
d.append(6)
print("After append(6):", d)
# Append left
d.appendleft(0)
print("After appendleft(0):", d)
# Pop from the right end
rightmost = d.pop()
print("Popped from right end:", rightmost)
print("Deque after pop():", d)
# Pop from the left end
leftmost = d.popleft()
print("Popped from left end:", leftmost)
print("Deque after popleft():", d)
# Accessing elements
print("Element at index 2:", d[2])
# Extend deque
d.extend([6, 7, 8])
print("After extend([6, 7, 8]):", d)
# Extend left
d.extendleft([-1, 0])
print("After extendleft([-1, 0]):", d)
# Rotate deque
d.rotate(2)
print("After rotate(2):", d)
# Rotate left
d.rotate(-3)
print("After rotate(-3):", d)
```
Output
```py
Initial deque: deque([1, 2, 3, 4, 5])
After append(6): deque([1, 2, 3, 4, 5, 6])
After appendleft(0): deque([0, 1, 2, 3, 4, 5, 6])
Popped from right end: 6
Deque after pop(): deque([0, 1, 2, 3, 4, 5])
Popped from left end: 0
Deque after popleft(): deque([1, 2, 3, 4, 5])
Element at index 2: 3
After extend([6, 7, 8]): deque([1, 2, 3, 4, 5, 6, 7, 8])
After extendleft([-1, 0]): deque([0, -1, 1, 2, 3, 4, 5, 6, 7, 8])
After rotate(2): deque([7, 8, 0, -1, 1, 2, 3, 4, 5, 6])
After rotate(-3): deque([1, 2, 3, 4, 5, 6, 7, 8, 0, -1])
```
### 2. Finding Maximum in Sliding Window
```py
from collections import deque
def max_sliding_window(nums, k):
if not nums:
return []
n = len(nums)
d = deque()
result = []
dq = deque()
for i in range(n):
# Remove elements from the deque that are out of the current window
while dq and dq[0] <= i - k:
dq.popleft()
# Remove elements from the deque that are less than the current element
while dq and nums[dq[-1]] <= nums[i]:
dq.pop()
# Add the current element index to the deque
dq.append(i)
# Add the maximum of the current window to the result
for i, num in enumerate(nums):
# Remove elements from deque that are out of the current window
if d and d[0] <= i - k:
d.popleft()
# Remove elements from deque smaller than the current element
while d and nums[d[-1]] <= num:
d.pop()
d.append(i)
# Add maximum for current window
if i >= k - 1:
result.append(nums[dq[0]])
result.append(nums[d[0]])
return result
# Example usage:
nums = [1, 3, -1, -3, 5, 3, 6, 7]
k = 3
print("Sliding Window Maximum:", sliding_window_maximum(nums, k))
print("Maximums in sliding window of size", k, "are:", max_sliding_window(nums, k))
```
## Conclusion
Output
```py
Maximums in sliding window of size 3 are: [3, 3, 5, 5, 6, 7]
```
Queues and deques are fundamental data structures that facilitate efficient data processing and
management in various applications. Understanding their principles and implementations is crucial
for developing robust software solutions.
## Applications
- **Efficient Queues and Stacks**: Deques allow fast O(1) append and pop operations from both ends,
making them ideal for implementing queues and stacks.
- **Sliding Window Maximum/Minimum**: Used in algorithms that require efficient windowed
computations.
## Advantages
- Efficiency: O(1) time complexity for append and pop operations from both ends.
- Versatility: Can function both as a queue and as a stack.
- Flexible: Supports rotation and slicing operations efficiently.
## Disadvantages
- Memory Usage: Requires more memory compared to simple lists due to overhead in managing linked
nodes.
## Conclusion
- Deques in Python, provided by the collections.deque module, offer efficient double-ended queue
operations with O(1) time complexity for append and pop operations on both ends. They are versatile
data structures suitable for implementing queues, stacks, and more complex algorithms requiring
efficient manipulation of elements at both ends.
- While deques excel in scenarios requiring fast append and pop operations from either end, they do
consume more memory compared to simple lists due to their implementation using doubly-linked lists.
However, their flexibility and efficiency make them invaluable for various programming tasks and
algorithmic solutions.