kopia lustrzana https://github.com/animator/learn-python
added deque
rodzic
8ee6007bbf
commit
fd466af7e0
|
@ -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.
|
```py
|
||||||
|
|
||||||
### 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
|
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
# Creating a deque
|
# Creating a deque
|
||||||
dq = deque()
|
d = deque(iterable) # Create deque from iterable (optional)
|
||||||
|
|
||||||
# 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))
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 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
|
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:
|
if not nums:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
n = len(nums)
|
d = deque()
|
||||||
result = []
|
result = []
|
||||||
dq = deque()
|
|
||||||
|
for i, num in enumerate(nums):
|
||||||
for i in range(n):
|
# Remove elements from deque that are out of the current window
|
||||||
# Remove elements from the deque that are out of the current window
|
if d and d[0] <= i - k:
|
||||||
while dq and dq[0] <= i - k:
|
d.popleft()
|
||||||
dq.popleft()
|
|
||||||
|
# Remove elements from deque smaller than the current element
|
||||||
# Remove elements from the deque that are less than the current element
|
while d and nums[d[-1]] <= num:
|
||||||
while dq and nums[dq[-1]] <= nums[i]:
|
d.pop()
|
||||||
dq.pop()
|
|
||||||
|
d.append(i)
|
||||||
# Add the current element index to the deque
|
|
||||||
dq.append(i)
|
# Add maximum for current window
|
||||||
|
|
||||||
# Add the maximum of the current window to the result
|
|
||||||
if i >= k - 1:
|
if i >= k - 1:
|
||||||
result.append(nums[dq[0]])
|
result.append(nums[d[0]])
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# Example usage:
|
# Example usage:
|
||||||
nums = [1, 3, -1, -3, 5, 3, 6, 7]
|
nums = [1, 3, -1, -3, 5, 3, 6, 7]
|
||||||
k = 3
|
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
|
## Applications
|
||||||
for developing robust software solutions.
|
- **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.
|
Ładowanie…
Reference in New Issue