pythonstl 0.1.4__cp311-cp311-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pythonstl/__init__.py +64 -0
- pythonstl/_rust.cp311-win_amd64.pyd +0 -0
- pythonstl/core/__init__.py +32 -0
- pythonstl/core/base.py +51 -0
- pythonstl/core/exceptions.py +57 -0
- pythonstl/core/iterator.py +187 -0
- pythonstl/facade/__init__.py +10 -0
- pythonstl/facade/algorithms.py +331 -0
- pythonstl/facade/map.py +298 -0
- pythonstl/facade/priority_queue.py +228 -0
- pythonstl/facade/queue.py +234 -0
- pythonstl/facade/set.py +271 -0
- pythonstl/facade/stack.py +217 -0
- pythonstl/facade/vector.py +406 -0
- pythonstl/implementations/__init__.py +3 -0
- pythonstl/implementations/associative/__init__.py +6 -0
- pythonstl/implementations/associative/_map_impl.py +164 -0
- pythonstl/implementations/associative/_set_impl.py +138 -0
- pythonstl/implementations/heaps/__init__.py +5 -0
- pythonstl/implementations/heaps/_priority_queue_impl.py +118 -0
- pythonstl/implementations/linear/__init__.py +7 -0
- pythonstl/implementations/linear/_queue_impl.py +117 -0
- pythonstl/implementations/linear/_stack_impl.py +99 -0
- pythonstl/implementations/linear/_vector_impl.py +251 -0
- pythonstl-0.1.4.dist-info/METADATA +449 -0
- pythonstl-0.1.4.dist-info/RECORD +29 -0
- pythonstl-0.1.4.dist-info/WHEEL +4 -0
- pythonstl-0.1.4.dist-info/licenses/LICENSE +21 -0
- pythonstl-0.1.4.dist-info/sboms/pythonstl.cyclonedx.json +1051 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Priority Queue facade class.
|
|
3
|
+
|
|
4
|
+
This module provides the public-facing priority_queue class that users interact with.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import TypeVar
|
|
8
|
+
from copy import deepcopy
|
|
9
|
+
from pythonstl.core.exceptions import EmptyContainerError
|
|
10
|
+
from pythonstl.implementations.heaps._priority_queue_impl import _PriorityQueueImpl
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from pythonstl._rust import RustPriorityQueue
|
|
14
|
+
RUST_AVAILABLE = True
|
|
15
|
+
except ImportError:
|
|
16
|
+
RUST_AVAILABLE = False
|
|
17
|
+
|
|
18
|
+
T = TypeVar('T')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class priority_queue:
|
|
22
|
+
"""
|
|
23
|
+
A priority queue data structure following C++ STL semantics.
|
|
24
|
+
|
|
25
|
+
This is a container adapter that provides constant time lookup of the
|
|
26
|
+
largest (by default) or smallest element, at the expense of logarithmic
|
|
27
|
+
insertion and extraction.
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
>>> from pythonstl import priority_queue
|
|
31
|
+
>>> pq = priority_queue() # max-heap by default
|
|
32
|
+
>>> pq.push(10)
|
|
33
|
+
>>> pq.push(30)
|
|
34
|
+
>>> pq.push(20)
|
|
35
|
+
>>> pq.top()
|
|
36
|
+
30
|
|
37
|
+
>>> len(pq)
|
|
38
|
+
3
|
|
39
|
+
>>>
|
|
40
|
+
>>> pq_min = priority_queue(comparator="min") # min-heap
|
|
41
|
+
>>> pq_min.push(10)
|
|
42
|
+
>>> pq_min.push(30)
|
|
43
|
+
>>> pq_min.push(20)
|
|
44
|
+
>>> pq_min.top()
|
|
45
|
+
10
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(self, comparator: str = "max", use_rust: bool = True) -> None:
|
|
49
|
+
"""
|
|
50
|
+
Initialize an empty priority queue.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
comparator: Either "max" for max-heap (default, matches C++ STL)
|
|
54
|
+
or "min" for min-heap.
|
|
55
|
+
|
|
56
|
+
Time Complexity:
|
|
57
|
+
O(1)
|
|
58
|
+
"""
|
|
59
|
+
if use_rust and RUST_AVAILABLE:
|
|
60
|
+
self._impl = RustPriorityQueue(comparator)
|
|
61
|
+
self._is_rust = True
|
|
62
|
+
else:
|
|
63
|
+
self._impl = _PriorityQueueImpl(comparator)
|
|
64
|
+
self._is_rust = False
|
|
65
|
+
self._comparator = comparator
|
|
66
|
+
|
|
67
|
+
def push(self, value: T) -> None:
|
|
68
|
+
"""
|
|
69
|
+
Insert an element into the priority queue.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
value: The element to insert.
|
|
73
|
+
|
|
74
|
+
Time Complexity:
|
|
75
|
+
O(log n) where n is the number of elements
|
|
76
|
+
"""
|
|
77
|
+
self._impl.push(value)
|
|
78
|
+
|
|
79
|
+
def pop(self) -> None:
|
|
80
|
+
"""
|
|
81
|
+
Remove the top element from the priority queue.
|
|
82
|
+
|
|
83
|
+
Raises:
|
|
84
|
+
EmptyContainerError: If the priority queue is empty.
|
|
85
|
+
|
|
86
|
+
Time Complexity:
|
|
87
|
+
O(log n) where n is the number of elements
|
|
88
|
+
"""
|
|
89
|
+
if self.empty():
|
|
90
|
+
raise EmptyContainerError("priority_queue")
|
|
91
|
+
self._impl.pop()
|
|
92
|
+
|
|
93
|
+
def top(self) -> T:
|
|
94
|
+
"""
|
|
95
|
+
Get the top element of the priority queue without removing it.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
The top element (highest priority for max-heap, lowest for min-heap).
|
|
99
|
+
|
|
100
|
+
Raises:
|
|
101
|
+
EmptyContainerError: If the priority queue is empty.
|
|
102
|
+
|
|
103
|
+
Time Complexity:
|
|
104
|
+
O(1)
|
|
105
|
+
"""
|
|
106
|
+
if self.empty():
|
|
107
|
+
raise EmptyContainerError("priority_queue")
|
|
108
|
+
return self._impl.top()
|
|
109
|
+
|
|
110
|
+
def empty(self) -> bool:
|
|
111
|
+
"""
|
|
112
|
+
Check if the priority queue is empty.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
True if the priority queue is empty, False otherwise.
|
|
116
|
+
|
|
117
|
+
Time Complexity:
|
|
118
|
+
O(1)
|
|
119
|
+
"""
|
|
120
|
+
return self._impl.empty()
|
|
121
|
+
|
|
122
|
+
def size(self) -> int:
|
|
123
|
+
"""
|
|
124
|
+
Get the number of elements in the priority queue.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
The number of elements in the priority queue.
|
|
128
|
+
|
|
129
|
+
Time Complexity:
|
|
130
|
+
O(1)
|
|
131
|
+
"""
|
|
132
|
+
return self._impl.size()
|
|
133
|
+
|
|
134
|
+
def copy(self) -> 'priority_queue':
|
|
135
|
+
"""
|
|
136
|
+
Create a deep copy of the priority queue.
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
A new priority queue with copied elements.
|
|
140
|
+
|
|
141
|
+
Time Complexity:
|
|
142
|
+
O(n) where n is the number of elements
|
|
143
|
+
"""
|
|
144
|
+
new_pq = priority_queue(self._comparator, use_rust=self._is_rust)
|
|
145
|
+
if self._is_rust:
|
|
146
|
+
new_pq._impl.set_data(self._impl.get_data())
|
|
147
|
+
else:
|
|
148
|
+
new_pq._impl._data = self._impl._data.copy()
|
|
149
|
+
return new_pq
|
|
150
|
+
|
|
151
|
+
# Python magic methods
|
|
152
|
+
|
|
153
|
+
def __len__(self) -> int:
|
|
154
|
+
"""
|
|
155
|
+
Get the number of elements (Python len() support).
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
The number of elements in the priority queue.
|
|
159
|
+
"""
|
|
160
|
+
return self.size()
|
|
161
|
+
|
|
162
|
+
def __bool__(self) -> bool:
|
|
163
|
+
"""
|
|
164
|
+
Check if priority queue is non-empty (Python bool() support).
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
True if priority queue is non-empty, False otherwise.
|
|
168
|
+
"""
|
|
169
|
+
return not self.empty()
|
|
170
|
+
|
|
171
|
+
def __repr__(self) -> str:
|
|
172
|
+
"""
|
|
173
|
+
Get string representation of the priority queue.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
String representation showing heap type and size.
|
|
177
|
+
"""
|
|
178
|
+
return f"priority_queue(comparator='{self._comparator}', size={self.size()})"
|
|
179
|
+
|
|
180
|
+
def __eq__(self, other: object) -> bool:
|
|
181
|
+
"""
|
|
182
|
+
Check equality with another priority queue.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
other: Another priority queue to compare with.
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
True if priority queues are equal, False otherwise.
|
|
189
|
+
"""
|
|
190
|
+
if not isinstance(other, priority_queue):
|
|
191
|
+
return False
|
|
192
|
+
if self._comparator != other._comparator:
|
|
193
|
+
return False
|
|
194
|
+
|
|
195
|
+
self_data = self._impl.get_data() if self._is_rust else self._impl._data
|
|
196
|
+
other_data = other._impl.get_data() if other._is_rust else other._impl._data
|
|
197
|
+
return self_data == other_data
|
|
198
|
+
|
|
199
|
+
def __copy__(self) -> 'priority_queue':
|
|
200
|
+
"""
|
|
201
|
+
Support for copy.copy().
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
A shallow copy of the priority queue.
|
|
205
|
+
"""
|
|
206
|
+
return self.copy()
|
|
207
|
+
|
|
208
|
+
def __deepcopy__(self, memo) -> 'priority_queue':
|
|
209
|
+
"""
|
|
210
|
+
Support for copy.deepcopy().
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
memo: Memoization dictionary for deepcopy.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
A deep copy of the priority queue.
|
|
217
|
+
"""
|
|
218
|
+
new_pq = priority_queue(self._comparator, use_rust=self._is_rust)
|
|
219
|
+
if self._is_rust:
|
|
220
|
+
new_data = deepcopy(self._impl.get_data(), memo)
|
|
221
|
+
new_pq._impl.set_data(new_data)
|
|
222
|
+
else:
|
|
223
|
+
new_pq._impl._data = deepcopy(self._impl._data, memo)
|
|
224
|
+
return new_pq
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
__all__ = ['priority_queue']
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Queue facade class.
|
|
3
|
+
|
|
4
|
+
This module provides the public-facing queue class that users interact with.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import TypeVar
|
|
8
|
+
from copy import deepcopy
|
|
9
|
+
from pythonstl.core.exceptions import EmptyContainerError
|
|
10
|
+
from pythonstl.implementations.linear._queue_impl import _QueueImpl
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from pythonstl._rust import RustQueue
|
|
14
|
+
RUST_AVAILABLE = True
|
|
15
|
+
except ImportError:
|
|
16
|
+
RUST_AVAILABLE = False
|
|
17
|
+
|
|
18
|
+
T = TypeVar('T')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class queue:
|
|
22
|
+
"""
|
|
23
|
+
A queue data structure following C++ STL semantics.
|
|
24
|
+
|
|
25
|
+
This is a FIFO (First-In-First-Out) container adapter.
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
>>> from pythonstl import queue
|
|
29
|
+
>>> q = queue()
|
|
30
|
+
>>> q.push(10)
|
|
31
|
+
>>> q.push(20)
|
|
32
|
+
>>> q.front()
|
|
33
|
+
10
|
|
34
|
+
>>> len(q)
|
|
35
|
+
2
|
|
36
|
+
>>> bool(q)
|
|
37
|
+
True
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(self, use_rust: bool = True) -> None:
|
|
41
|
+
"""
|
|
42
|
+
Initialize an empty queue.
|
|
43
|
+
|
|
44
|
+
Time Complexity:
|
|
45
|
+
O(1)
|
|
46
|
+
"""
|
|
47
|
+
if use_rust and RUST_AVAILABLE:
|
|
48
|
+
self._impl = RustQueue()
|
|
49
|
+
self._is_rust = True
|
|
50
|
+
else:
|
|
51
|
+
self._impl = _QueueImpl()
|
|
52
|
+
self._is_rust = False
|
|
53
|
+
|
|
54
|
+
def push(self, value: T) -> None:
|
|
55
|
+
"""
|
|
56
|
+
Add an element to the back of the queue.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
value: The element to add to the queue.
|
|
60
|
+
|
|
61
|
+
Time Complexity:
|
|
62
|
+
O(1)
|
|
63
|
+
"""
|
|
64
|
+
self._impl.push(value)
|
|
65
|
+
|
|
66
|
+
def pop(self) -> None:
|
|
67
|
+
"""
|
|
68
|
+
Remove the front element from the queue.
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
EmptyContainerError: If the queue is empty.
|
|
72
|
+
|
|
73
|
+
Time Complexity:
|
|
74
|
+
O(1)
|
|
75
|
+
"""
|
|
76
|
+
if self.empty():
|
|
77
|
+
raise EmptyContainerError("queue")
|
|
78
|
+
self._impl.pop()
|
|
79
|
+
|
|
80
|
+
def front(self) -> T:
|
|
81
|
+
"""
|
|
82
|
+
Get the front element of the queue without removing it.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
The front element of the queue.
|
|
86
|
+
|
|
87
|
+
Raises:
|
|
88
|
+
EmptyContainerError: If the queue is empty.
|
|
89
|
+
|
|
90
|
+
Time Complexity:
|
|
91
|
+
O(1)
|
|
92
|
+
"""
|
|
93
|
+
if self.empty():
|
|
94
|
+
raise EmptyContainerError("queue")
|
|
95
|
+
return self._impl.front()
|
|
96
|
+
|
|
97
|
+
def back(self) -> T:
|
|
98
|
+
"""
|
|
99
|
+
Get the back element of the queue without removing it.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
The back element of the queue.
|
|
103
|
+
|
|
104
|
+
Raises:
|
|
105
|
+
EmptyContainerError: If the queue is empty.
|
|
106
|
+
|
|
107
|
+
Time Complexity:
|
|
108
|
+
O(1)
|
|
109
|
+
"""
|
|
110
|
+
if self.empty():
|
|
111
|
+
raise EmptyContainerError("queue")
|
|
112
|
+
return self._impl.back()
|
|
113
|
+
|
|
114
|
+
def empty(self) -> bool:
|
|
115
|
+
"""
|
|
116
|
+
Check if the queue is empty.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
True if the queue is empty, False otherwise.
|
|
120
|
+
|
|
121
|
+
Time Complexity:
|
|
122
|
+
O(1)
|
|
123
|
+
"""
|
|
124
|
+
return self._impl.empty()
|
|
125
|
+
|
|
126
|
+
def size(self) -> int:
|
|
127
|
+
"""
|
|
128
|
+
Get the number of elements in the queue.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
The number of elements in the queue.
|
|
132
|
+
|
|
133
|
+
Time Complexity:
|
|
134
|
+
O(1)
|
|
135
|
+
"""
|
|
136
|
+
return self._impl.size()
|
|
137
|
+
|
|
138
|
+
def copy(self) -> 'queue':
|
|
139
|
+
"""
|
|
140
|
+
Create a deep copy of the queue.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
A new queue with copied elements.
|
|
144
|
+
|
|
145
|
+
Time Complexity:
|
|
146
|
+
O(n) where n is the number of elements
|
|
147
|
+
"""
|
|
148
|
+
new_queue = queue(use_rust=self._is_rust)
|
|
149
|
+
if self._is_rust:
|
|
150
|
+
new_queue._impl.set_data(self._impl.get_data())
|
|
151
|
+
else:
|
|
152
|
+
new_queue._impl._data = self._impl._data.copy()
|
|
153
|
+
return new_queue
|
|
154
|
+
|
|
155
|
+
# Python magic methods
|
|
156
|
+
|
|
157
|
+
def __len__(self) -> int:
|
|
158
|
+
"""
|
|
159
|
+
Get the number of elements (Python len() support).
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
The number of elements in the queue.
|
|
163
|
+
"""
|
|
164
|
+
return self.size()
|
|
165
|
+
|
|
166
|
+
def __bool__(self) -> bool:
|
|
167
|
+
"""
|
|
168
|
+
Check if queue is non-empty (Python bool() support).
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
True if queue is non-empty, False otherwise.
|
|
172
|
+
"""
|
|
173
|
+
return not self.empty()
|
|
174
|
+
|
|
175
|
+
def __repr__(self) -> str:
|
|
176
|
+
"""
|
|
177
|
+
Get string representation of the queue.
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
String representation showing queue contents.
|
|
181
|
+
"""
|
|
182
|
+
if self._is_rust:
|
|
183
|
+
elements = [str(elem) for elem in self._impl.get_data()]
|
|
184
|
+
else:
|
|
185
|
+
elements = [str(elem) for elem in self._impl._data]
|
|
186
|
+
return f"queue([{', '.join(elements)}])"
|
|
187
|
+
|
|
188
|
+
def __eq__(self, other: object) -> bool:
|
|
189
|
+
"""
|
|
190
|
+
Check equality with another queue.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
other: Another queue to compare with.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
True if queues are equal, False otherwise.
|
|
197
|
+
"""
|
|
198
|
+
if not isinstance(other, queue):
|
|
199
|
+
return False
|
|
200
|
+
|
|
201
|
+
self_data = self._impl.get_data() if self._is_rust else self._impl._data
|
|
202
|
+
other_data = other._impl.get_data() if other._is_rust else other._impl._data
|
|
203
|
+
return self_data == other_data
|
|
204
|
+
|
|
205
|
+
def __copy__(self) -> 'queue':
|
|
206
|
+
"""
|
|
207
|
+
Support for copy.copy().
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
A shallow copy of the queue.
|
|
211
|
+
"""
|
|
212
|
+
return self.copy()
|
|
213
|
+
|
|
214
|
+
def __deepcopy__(self, memo) -> 'queue':
|
|
215
|
+
"""
|
|
216
|
+
Support for copy.deepcopy().
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
memo: Memoization dictionary for deepcopy.
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
A deep copy of the queue.
|
|
223
|
+
"""
|
|
224
|
+
new_queue = queue(use_rust=self._is_rust)
|
|
225
|
+
if self._is_rust:
|
|
226
|
+
new_data = deepcopy(self._impl.get_data(), memo)
|
|
227
|
+
new_queue._impl.set_data(new_data)
|
|
228
|
+
else:
|
|
229
|
+
new_queue._impl._data = deepcopy(self._impl._data, memo)
|
|
230
|
+
return new_queue
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
__all__ = ['queue']
|