exonware-xwnode 0.0.1.12__py3-none-any.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.
- exonware/__init__.py +14 -0
- exonware/xwnode/__init__.py +127 -0
- exonware/xwnode/base.py +676 -0
- exonware/xwnode/config.py +178 -0
- exonware/xwnode/contracts.py +730 -0
- exonware/xwnode/errors.py +503 -0
- exonware/xwnode/facade.py +460 -0
- exonware/xwnode/strategies/__init__.py +158 -0
- exonware/xwnode/strategies/advisor.py +463 -0
- exonware/xwnode/strategies/edges/__init__.py +32 -0
- exonware/xwnode/strategies/edges/adj_list.py +227 -0
- exonware/xwnode/strategies/edges/adj_matrix.py +391 -0
- exonware/xwnode/strategies/edges/base.py +169 -0
- exonware/xwnode/strategies/flyweight.py +328 -0
- exonware/xwnode/strategies/impls/__init__.py +13 -0
- exonware/xwnode/strategies/impls/_base_edge.py +403 -0
- exonware/xwnode/strategies/impls/_base_node.py +307 -0
- exonware/xwnode/strategies/impls/edge_adj_list.py +353 -0
- exonware/xwnode/strategies/impls/edge_adj_matrix.py +445 -0
- exonware/xwnode/strategies/impls/edge_bidir_wrapper.py +455 -0
- exonware/xwnode/strategies/impls/edge_block_adj_matrix.py +539 -0
- exonware/xwnode/strategies/impls/edge_coo.py +533 -0
- exonware/xwnode/strategies/impls/edge_csc.py +447 -0
- exonware/xwnode/strategies/impls/edge_csr.py +492 -0
- exonware/xwnode/strategies/impls/edge_dynamic_adj_list.py +503 -0
- exonware/xwnode/strategies/impls/edge_flow_network.py +555 -0
- exonware/xwnode/strategies/impls/edge_hyperedge_set.py +516 -0
- exonware/xwnode/strategies/impls/edge_neural_graph.py +650 -0
- exonware/xwnode/strategies/impls/edge_octree.py +574 -0
- exonware/xwnode/strategies/impls/edge_property_store.py +655 -0
- exonware/xwnode/strategies/impls/edge_quadtree.py +519 -0
- exonware/xwnode/strategies/impls/edge_rtree.py +820 -0
- exonware/xwnode/strategies/impls/edge_temporal_edgeset.py +558 -0
- exonware/xwnode/strategies/impls/edge_tree_graph_basic.py +271 -0
- exonware/xwnode/strategies/impls/edge_weighted_graph.py +411 -0
- exonware/xwnode/strategies/manager.py +775 -0
- exonware/xwnode/strategies/metrics.py +538 -0
- exonware/xwnode/strategies/migration.py +432 -0
- exonware/xwnode/strategies/nodes/__init__.py +50 -0
- exonware/xwnode/strategies/nodes/_base_node.py +307 -0
- exonware/xwnode/strategies/nodes/adjacency_list.py +267 -0
- exonware/xwnode/strategies/nodes/aho_corasick.py +345 -0
- exonware/xwnode/strategies/nodes/array_list.py +209 -0
- exonware/xwnode/strategies/nodes/base.py +247 -0
- exonware/xwnode/strategies/nodes/deque.py +200 -0
- exonware/xwnode/strategies/nodes/hash_map.py +135 -0
- exonware/xwnode/strategies/nodes/heap.py +307 -0
- exonware/xwnode/strategies/nodes/linked_list.py +232 -0
- exonware/xwnode/strategies/nodes/node_aho_corasick.py +520 -0
- exonware/xwnode/strategies/nodes/node_array_list.py +175 -0
- exonware/xwnode/strategies/nodes/node_avl_tree.py +371 -0
- exonware/xwnode/strategies/nodes/node_b_plus_tree.py +542 -0
- exonware/xwnode/strategies/nodes/node_bitmap.py +420 -0
- exonware/xwnode/strategies/nodes/node_bitset_dynamic.py +513 -0
- exonware/xwnode/strategies/nodes/node_bloom_filter.py +347 -0
- exonware/xwnode/strategies/nodes/node_btree.py +357 -0
- exonware/xwnode/strategies/nodes/node_count_min_sketch.py +470 -0
- exonware/xwnode/strategies/nodes/node_cow_tree.py +473 -0
- exonware/xwnode/strategies/nodes/node_cuckoo_hash.py +392 -0
- exonware/xwnode/strategies/nodes/node_fenwick_tree.py +301 -0
- exonware/xwnode/strategies/nodes/node_hash_map.py +269 -0
- exonware/xwnode/strategies/nodes/node_heap.py +191 -0
- exonware/xwnode/strategies/nodes/node_hyperloglog.py +407 -0
- exonware/xwnode/strategies/nodes/node_linked_list.py +409 -0
- exonware/xwnode/strategies/nodes/node_lsm_tree.py +400 -0
- exonware/xwnode/strategies/nodes/node_ordered_map.py +390 -0
- exonware/xwnode/strategies/nodes/node_ordered_map_balanced.py +565 -0
- exonware/xwnode/strategies/nodes/node_patricia.py +512 -0
- exonware/xwnode/strategies/nodes/node_persistent_tree.py +378 -0
- exonware/xwnode/strategies/nodes/node_radix_trie.py +452 -0
- exonware/xwnode/strategies/nodes/node_red_black_tree.py +497 -0
- exonware/xwnode/strategies/nodes/node_roaring_bitmap.py +570 -0
- exonware/xwnode/strategies/nodes/node_segment_tree.py +289 -0
- exonware/xwnode/strategies/nodes/node_set_hash.py +354 -0
- exonware/xwnode/strategies/nodes/node_set_tree.py +480 -0
- exonware/xwnode/strategies/nodes/node_skip_list.py +316 -0
- exonware/xwnode/strategies/nodes/node_splay_tree.py +393 -0
- exonware/xwnode/strategies/nodes/node_suffix_array.py +487 -0
- exonware/xwnode/strategies/nodes/node_treap.py +387 -0
- exonware/xwnode/strategies/nodes/node_tree_graph_hybrid.py +1434 -0
- exonware/xwnode/strategies/nodes/node_trie.py +252 -0
- exonware/xwnode/strategies/nodes/node_union_find.py +187 -0
- exonware/xwnode/strategies/nodes/node_xdata_optimized.py +369 -0
- exonware/xwnode/strategies/nodes/priority_queue.py +209 -0
- exonware/xwnode/strategies/nodes/queue.py +161 -0
- exonware/xwnode/strategies/nodes/sparse_matrix.py +206 -0
- exonware/xwnode/strategies/nodes/stack.py +152 -0
- exonware/xwnode/strategies/nodes/trie.py +274 -0
- exonware/xwnode/strategies/nodes/union_find.py +283 -0
- exonware/xwnode/strategies/pattern_detector.py +603 -0
- exonware/xwnode/strategies/performance_monitor.py +487 -0
- exonware/xwnode/strategies/queries/__init__.py +24 -0
- exonware/xwnode/strategies/queries/base.py +236 -0
- exonware/xwnode/strategies/queries/cql.py +201 -0
- exonware/xwnode/strategies/queries/cypher.py +181 -0
- exonware/xwnode/strategies/queries/datalog.py +70 -0
- exonware/xwnode/strategies/queries/elastic_dsl.py +70 -0
- exonware/xwnode/strategies/queries/eql.py +70 -0
- exonware/xwnode/strategies/queries/flux.py +70 -0
- exonware/xwnode/strategies/queries/gql.py +70 -0
- exonware/xwnode/strategies/queries/graphql.py +240 -0
- exonware/xwnode/strategies/queries/gremlin.py +181 -0
- exonware/xwnode/strategies/queries/hiveql.py +214 -0
- exonware/xwnode/strategies/queries/hql.py +70 -0
- exonware/xwnode/strategies/queries/jmespath.py +219 -0
- exonware/xwnode/strategies/queries/jq.py +66 -0
- exonware/xwnode/strategies/queries/json_query.py +66 -0
- exonware/xwnode/strategies/queries/jsoniq.py +248 -0
- exonware/xwnode/strategies/queries/kql.py +70 -0
- exonware/xwnode/strategies/queries/linq.py +238 -0
- exonware/xwnode/strategies/queries/logql.py +70 -0
- exonware/xwnode/strategies/queries/mql.py +68 -0
- exonware/xwnode/strategies/queries/n1ql.py +210 -0
- exonware/xwnode/strategies/queries/partiql.py +70 -0
- exonware/xwnode/strategies/queries/pig.py +215 -0
- exonware/xwnode/strategies/queries/promql.py +70 -0
- exonware/xwnode/strategies/queries/sparql.py +220 -0
- exonware/xwnode/strategies/queries/sql.py +275 -0
- exonware/xwnode/strategies/queries/xml_query.py +66 -0
- exonware/xwnode/strategies/queries/xpath.py +223 -0
- exonware/xwnode/strategies/queries/xquery.py +258 -0
- exonware/xwnode/strategies/queries/xwnode_executor.py +332 -0
- exonware/xwnode/strategies/queries/xwquery_strategy.py +424 -0
- exonware/xwnode/strategies/registry.py +604 -0
- exonware/xwnode/strategies/simple.py +273 -0
- exonware/xwnode/strategies/utils.py +532 -0
- exonware/xwnode/types.py +912 -0
- exonware/xwnode/version.py +78 -0
- exonware_xwnode-0.0.1.12.dist-info/METADATA +169 -0
- exonware_xwnode-0.0.1.12.dist-info/RECORD +132 -0
- exonware_xwnode-0.0.1.12.dist-info/WHEEL +4 -0
- exonware_xwnode-0.0.1.12.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,307 @@
|
|
1
|
+
"""
|
2
|
+
Heap Node Strategy Implementation
|
3
|
+
|
4
|
+
This module implements the HEAP strategy for priority queue operations.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import heapq
|
8
|
+
from typing import Any, Iterator, List, Optional, Dict
|
9
|
+
from .base import ANodeTreeStrategy
|
10
|
+
from ...types import NodeMode, NodeTrait
|
11
|
+
|
12
|
+
|
13
|
+
class MinHeap:
|
14
|
+
"""Min heap implementation."""
|
15
|
+
|
16
|
+
def __init__(self, max_heap: bool = False):
|
17
|
+
self._heap = []
|
18
|
+
self._max_heap = max_heap
|
19
|
+
self._counter = 0 # For stable sorting
|
20
|
+
|
21
|
+
def push(self, priority: float, value: Any) -> None:
|
22
|
+
"""Push item with priority."""
|
23
|
+
if self._max_heap:
|
24
|
+
priority = -priority
|
25
|
+
heapq.heappush(self._heap, (priority, self._counter, value))
|
26
|
+
self._counter += 1
|
27
|
+
|
28
|
+
def pop(self) -> Any:
|
29
|
+
"""Pop item with highest priority."""
|
30
|
+
if not self._heap:
|
31
|
+
raise IndexError("pop from empty heap")
|
32
|
+
priority, _, value = heapq.heappop(self._heap)
|
33
|
+
return value
|
34
|
+
|
35
|
+
def peek(self) -> Any:
|
36
|
+
"""Peek at highest priority item."""
|
37
|
+
if not self._heap:
|
38
|
+
raise IndexError("peek from empty heap")
|
39
|
+
return self._heap[0][2]
|
40
|
+
|
41
|
+
def size(self) -> int:
|
42
|
+
"""Get heap size."""
|
43
|
+
return len(self._heap)
|
44
|
+
|
45
|
+
def is_empty(self) -> bool:
|
46
|
+
"""Check if heap is empty."""
|
47
|
+
return len(self._heap) == 0
|
48
|
+
|
49
|
+
|
50
|
+
class xHeapStrategy(ANodeTreeStrategy):
|
51
|
+
"""
|
52
|
+
Heap node strategy for priority queue operations.
|
53
|
+
|
54
|
+
Optimized for push, pop, and peek operations with configurable min/max behavior.
|
55
|
+
"""
|
56
|
+
|
57
|
+
def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
|
58
|
+
"""Initialize the heap strategy."""
|
59
|
+
super().__init__(data=None, **options)
|
60
|
+
self._mode = NodeMode.HEAP
|
61
|
+
self._traits = traits
|
62
|
+
self._is_max_heap = options.get('max_heap', False)
|
63
|
+
self._heap = MinHeap(max_heap=self._is_max_heap)
|
64
|
+
self._size = 0
|
65
|
+
|
66
|
+
def get_supported_traits(self) -> NodeTrait:
|
67
|
+
"""Get the traits supported by the heap strategy."""
|
68
|
+
return (NodeTrait.ORDERED | NodeTrait.PRIORITY_QUEUE)
|
69
|
+
|
70
|
+
# ============================================================================
|
71
|
+
# CORE OPERATIONS
|
72
|
+
# ============================================================================
|
73
|
+
|
74
|
+
def insert(self, key: Any, value: Any) -> None:
|
75
|
+
"""Store a key-value pair (key is priority, value is data)."""
|
76
|
+
priority = float(key) if key is not None else 0.0
|
77
|
+
data = value if value is not None else key
|
78
|
+
self._heap.push(priority, data)
|
79
|
+
self._size += 1
|
80
|
+
|
81
|
+
def find(self, key: Any) -> Any:
|
82
|
+
"""Find value by priority (not efficient for heaps)."""
|
83
|
+
# Heaps don't support efficient lookup by priority
|
84
|
+
# This is a limitation of the heap data structure
|
85
|
+
return None
|
86
|
+
|
87
|
+
def delete(self, key: Any) -> bool:
|
88
|
+
"""Delete by priority (not efficient for heaps)."""
|
89
|
+
# Heaps don't support efficient deletion by priority
|
90
|
+
# This is a limitation of the heap data structure
|
91
|
+
return False
|
92
|
+
|
93
|
+
def size(self) -> int:
|
94
|
+
"""Get the number of items."""
|
95
|
+
return self._size
|
96
|
+
|
97
|
+
def is_empty(self) -> bool:
|
98
|
+
"""Check if the structure is empty."""
|
99
|
+
return self._size == 0
|
100
|
+
|
101
|
+
def to_native(self) -> List[Any]:
|
102
|
+
"""Convert to native Python list."""
|
103
|
+
# Return all values in priority order
|
104
|
+
result = []
|
105
|
+
temp_heap = MinHeap(max_heap=self._is_max_heap)
|
106
|
+
|
107
|
+
# Copy heap and extract all values
|
108
|
+
for item in self._heap._heap:
|
109
|
+
priority, counter, value = item
|
110
|
+
temp_heap._heap.append(item)
|
111
|
+
|
112
|
+
while not temp_heap.is_empty():
|
113
|
+
result.append(temp_heap.pop())
|
114
|
+
|
115
|
+
return result
|
116
|
+
|
117
|
+
# ============================================================================
|
118
|
+
# TREE STRATEGY METHODS
|
119
|
+
# ============================================================================
|
120
|
+
|
121
|
+
def traverse(self, order: str = 'inorder') -> List[Any]:
|
122
|
+
"""Traverse heap in priority order."""
|
123
|
+
return self.to_native()
|
124
|
+
|
125
|
+
def get_min(self) -> Any:
|
126
|
+
"""Get minimum priority item."""
|
127
|
+
if self._is_max_heap:
|
128
|
+
return None # No min in max heap
|
129
|
+
return self._heap.peek() if not self._heap.is_empty() else None
|
130
|
+
|
131
|
+
def get_max(self) -> Any:
|
132
|
+
"""Get maximum priority item."""
|
133
|
+
if not self._is_max_heap:
|
134
|
+
return None # No max in min heap
|
135
|
+
return self._heap.peek() if not self._heap.is_empty() else None
|
136
|
+
|
137
|
+
# ============================================================================
|
138
|
+
# AUTO-3 Phase 2 methods
|
139
|
+
# ============================================================================
|
140
|
+
|
141
|
+
def as_trie(self):
|
142
|
+
"""Provide Trie behavioral view."""
|
143
|
+
# TODO: Implement Trie view
|
144
|
+
return self
|
145
|
+
|
146
|
+
def as_heap(self):
|
147
|
+
"""Provide Heap behavioral view."""
|
148
|
+
return self
|
149
|
+
|
150
|
+
def as_skip_list(self):
|
151
|
+
"""Provide SkipList behavioral view."""
|
152
|
+
# TODO: Implement SkipList view
|
153
|
+
return self
|
154
|
+
|
155
|
+
# ============================================================================
|
156
|
+
# HEAP SPECIFIC OPERATIONS
|
157
|
+
# ============================================================================
|
158
|
+
|
159
|
+
def push(self, value: Any, priority: float = None) -> str:
|
160
|
+
"""Push a value with optional priority."""
|
161
|
+
if priority is None:
|
162
|
+
priority = float(value) if isinstance(value, (int, float)) else 0.0
|
163
|
+
self._heap.push(priority, value)
|
164
|
+
self._size += 1
|
165
|
+
return str(priority)
|
166
|
+
|
167
|
+
def pop(self) -> Any:
|
168
|
+
"""Remove and return highest priority item."""
|
169
|
+
if self._heap.is_empty():
|
170
|
+
raise IndexError("pop from empty heap")
|
171
|
+
value = self._heap.pop()
|
172
|
+
self._size -= 1
|
173
|
+
return value
|
174
|
+
|
175
|
+
def peek(self) -> Any:
|
176
|
+
"""Get highest priority item without removing."""
|
177
|
+
if self._heap.is_empty():
|
178
|
+
raise IndexError("peek from empty heap")
|
179
|
+
return self._heap.peek()
|
180
|
+
|
181
|
+
def peek_priority(self) -> float:
|
182
|
+
"""Get priority of highest priority item."""
|
183
|
+
if self._heap.is_empty():
|
184
|
+
raise IndexError("peek from empty heap")
|
185
|
+
# This is a simplified implementation
|
186
|
+
return 0.0
|
187
|
+
|
188
|
+
def pushpop(self, value: Any, priority: float = None) -> Any:
|
189
|
+
"""Push value and pop highest priority item."""
|
190
|
+
if priority is None:
|
191
|
+
priority = float(value) if isinstance(value, (int, float)) else 0.0
|
192
|
+
|
193
|
+
if self._heap.is_empty():
|
194
|
+
self._heap.push(priority, value)
|
195
|
+
return None
|
196
|
+
|
197
|
+
# Push new value
|
198
|
+
self._heap.push(priority, value)
|
199
|
+
# Pop highest priority
|
200
|
+
return self._heap.pop()
|
201
|
+
|
202
|
+
def replace(self, value: Any, priority: float = None) -> Any:
|
203
|
+
"""Replace highest priority item with new value."""
|
204
|
+
if self._heap.is_empty():
|
205
|
+
raise IndexError("replace from empty heap")
|
206
|
+
|
207
|
+
if priority is None:
|
208
|
+
priority = float(value) if isinstance(value, (int, float)) else 0.0
|
209
|
+
|
210
|
+
# Pop current highest
|
211
|
+
old_value = self._heap.pop()
|
212
|
+
# Push new value
|
213
|
+
self._heap.push(priority, value)
|
214
|
+
|
215
|
+
return old_value
|
216
|
+
|
217
|
+
def heapify(self) -> None:
|
218
|
+
"""Heapify the heap (already maintained)."""
|
219
|
+
# Heap is already heapified
|
220
|
+
pass
|
221
|
+
|
222
|
+
def nlargest(self, n: int) -> List[Any]:
|
223
|
+
"""Get n largest items."""
|
224
|
+
if self._is_max_heap:
|
225
|
+
# For max heap, get first n items
|
226
|
+
result = []
|
227
|
+
temp_heap = MinHeap(max_heap=True)
|
228
|
+
|
229
|
+
# Copy heap
|
230
|
+
for item in self._heap._heap:
|
231
|
+
temp_heap._heap.append(item)
|
232
|
+
|
233
|
+
for _ in range(min(n, self._size)):
|
234
|
+
if temp_heap.is_empty():
|
235
|
+
break
|
236
|
+
result.append(temp_heap.pop())
|
237
|
+
|
238
|
+
return result
|
239
|
+
else:
|
240
|
+
# For min heap, this is not efficient
|
241
|
+
return []
|
242
|
+
|
243
|
+
def nsmallest(self, n: int) -> List[Any]:
|
244
|
+
"""Get n smallest items."""
|
245
|
+
if not self._is_max_heap:
|
246
|
+
# For min heap, get first n items
|
247
|
+
result = []
|
248
|
+
temp_heap = MinHeap(max_heap=False)
|
249
|
+
|
250
|
+
# Copy heap
|
251
|
+
for item in self._heap._heap:
|
252
|
+
temp_heap._heap.append(item)
|
253
|
+
|
254
|
+
for _ in range(min(n, self._size)):
|
255
|
+
if temp_heap.is_empty():
|
256
|
+
break
|
257
|
+
result.append(temp_heap.pop())
|
258
|
+
|
259
|
+
return result
|
260
|
+
else:
|
261
|
+
# For max heap, this is not efficient
|
262
|
+
return []
|
263
|
+
|
264
|
+
# ============================================================================
|
265
|
+
# ITERATION
|
266
|
+
# ============================================================================
|
267
|
+
|
268
|
+
def keys(self) -> Iterator[str]:
|
269
|
+
"""Get all priorities as strings."""
|
270
|
+
# This is not efficient for heaps
|
271
|
+
return iter([])
|
272
|
+
|
273
|
+
def values(self) -> Iterator[Any]:
|
274
|
+
"""Get all values."""
|
275
|
+
return iter(self.to_native())
|
276
|
+
|
277
|
+
def items(self) -> Iterator[tuple[str, Any]]:
|
278
|
+
"""Get all priority-value pairs."""
|
279
|
+
# This is not efficient for heaps
|
280
|
+
return iter([])
|
281
|
+
|
282
|
+
# ============================================================================
|
283
|
+
# PERFORMANCE CHARACTERISTICS
|
284
|
+
# ============================================================================
|
285
|
+
|
286
|
+
@property
|
287
|
+
def backend_info(self) -> Dict[str, Any]:
|
288
|
+
"""Get backend implementation info."""
|
289
|
+
return {
|
290
|
+
'strategy': 'HEAP',
|
291
|
+
'backend': 'Python heapq',
|
292
|
+
'complexity': {
|
293
|
+
'push': 'O(log n)',
|
294
|
+
'pop': 'O(log n)',
|
295
|
+
'peek': 'O(1)',
|
296
|
+
'heapify': 'O(n)'
|
297
|
+
}
|
298
|
+
}
|
299
|
+
|
300
|
+
@property
|
301
|
+
def metrics(self) -> Dict[str, Any]:
|
302
|
+
"""Get performance metrics."""
|
303
|
+
return {
|
304
|
+
'size': self._size,
|
305
|
+
'is_max_heap': self._is_max_heap,
|
306
|
+
'memory_usage': f"{self._size * 24} bytes (estimated)"
|
307
|
+
}
|
@@ -0,0 +1,232 @@
|
|
1
|
+
"""
|
2
|
+
Linked List Node Strategy Implementation
|
3
|
+
|
4
|
+
This module implements the LINKED_LIST strategy for efficient
|
5
|
+
insertions and deletions with sequential access patterns.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from typing import Any, Iterator, List, Dict, Optional
|
9
|
+
from .base import ANodeLinearStrategy
|
10
|
+
from ...types import NodeMode, NodeTrait
|
11
|
+
|
12
|
+
|
13
|
+
class ListNode:
|
14
|
+
"""Node in the doubly linked list."""
|
15
|
+
|
16
|
+
def __init__(self, key: str, value: Any):
|
17
|
+
self.key = key
|
18
|
+
self.value = value
|
19
|
+
self.prev: Optional['ListNode'] = None
|
20
|
+
self.next: Optional['ListNode'] = None
|
21
|
+
|
22
|
+
|
23
|
+
class LinkedListStrategy(ANodeLinearStrategy):
|
24
|
+
"""
|
25
|
+
Linked List node strategy for efficient insertions and deletions.
|
26
|
+
|
27
|
+
Provides O(1) insertions/deletions at known positions with
|
28
|
+
sequential access patterns optimized for iteration.
|
29
|
+
"""
|
30
|
+
|
31
|
+
def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
|
32
|
+
"""Initialize the Linked List strategy."""
|
33
|
+
super().__init__(data=None, **options)
|
34
|
+
self._mode = NodeMode.LINKED_LIST
|
35
|
+
self._traits = traits
|
36
|
+
|
37
|
+
self.doubly_linked = options.get('doubly_linked', True)
|
38
|
+
|
39
|
+
# Doubly linked list with sentinel nodes
|
40
|
+
self._head = ListNode("HEAD", None)
|
41
|
+
self._tail = ListNode("TAIL", None)
|
42
|
+
self._head.next = self._tail
|
43
|
+
self._tail.prev = self._head
|
44
|
+
|
45
|
+
# Quick access mapping
|
46
|
+
self._key_to_node: Dict[str, ListNode] = {}
|
47
|
+
self._size = 0
|
48
|
+
|
49
|
+
def get_supported_traits(self) -> NodeTrait:
|
50
|
+
"""Get the traits supported by the linked list strategy."""
|
51
|
+
return (NodeTrait.ORDERED | NodeTrait.INDEXED)
|
52
|
+
|
53
|
+
# ============================================================================
|
54
|
+
# CORE OPERATIONS
|
55
|
+
# ============================================================================
|
56
|
+
|
57
|
+
def insert(self, key: Any, value: Any) -> None:
|
58
|
+
"""Insert key-value pair."""
|
59
|
+
key_str = str(key)
|
60
|
+
if key_str in self._key_to_node:
|
61
|
+
# Update existing
|
62
|
+
self._key_to_node[key_str].value = value
|
63
|
+
else:
|
64
|
+
# Insert new node at end
|
65
|
+
self._insert_at_end(key_str, value)
|
66
|
+
|
67
|
+
def find(self, key: Any) -> Any:
|
68
|
+
"""Find value by key."""
|
69
|
+
key_str = str(key)
|
70
|
+
node = self._key_to_node.get(key_str)
|
71
|
+
return node.value if node else None
|
72
|
+
|
73
|
+
def delete(self, key: Any) -> bool:
|
74
|
+
"""Delete by key."""
|
75
|
+
key_str = str(key)
|
76
|
+
if key_str in self._key_to_node:
|
77
|
+
self._remove_node(self._key_to_node[key_str])
|
78
|
+
del self._key_to_node[key_str]
|
79
|
+
return True
|
80
|
+
return False
|
81
|
+
|
82
|
+
def size(self) -> int:
|
83
|
+
"""Get size."""
|
84
|
+
return self._size
|
85
|
+
|
86
|
+
def is_empty(self) -> bool:
|
87
|
+
"""Check if empty."""
|
88
|
+
return self._size == 0
|
89
|
+
|
90
|
+
def to_native(self) -> List[Any]:
|
91
|
+
"""Convert to native list."""
|
92
|
+
result = []
|
93
|
+
current = self._head.next
|
94
|
+
while current != self._tail:
|
95
|
+
result.append(current.value)
|
96
|
+
current = current.next
|
97
|
+
return result
|
98
|
+
|
99
|
+
# ============================================================================
|
100
|
+
# LINEAR STRATEGY METHODS
|
101
|
+
# ============================================================================
|
102
|
+
|
103
|
+
def push_front(self, value: Any) -> None:
|
104
|
+
"""Add element to front."""
|
105
|
+
self._insert_after(self._head, str(self._size), value)
|
106
|
+
|
107
|
+
def push_back(self, value: Any) -> None:
|
108
|
+
"""Add element to back."""
|
109
|
+
self._insert_before(self._tail, str(self._size), value)
|
110
|
+
|
111
|
+
def pop_front(self) -> Any:
|
112
|
+
"""Remove element from front."""
|
113
|
+
if self._size == 0:
|
114
|
+
raise IndexError("pop from empty list")
|
115
|
+
first_node = self._head.next
|
116
|
+
value = first_node.value
|
117
|
+
self._remove_node(first_node)
|
118
|
+
return value
|
119
|
+
|
120
|
+
def pop_back(self) -> Any:
|
121
|
+
"""Remove element from back."""
|
122
|
+
if self._size == 0:
|
123
|
+
raise IndexError("pop from empty list")
|
124
|
+
last_node = self._tail.prev
|
125
|
+
value = last_node.value
|
126
|
+
self._remove_node(last_node)
|
127
|
+
return value
|
128
|
+
|
129
|
+
def get_at_index(self, index: int) -> Any:
|
130
|
+
"""Get element at index."""
|
131
|
+
if index < 0 or index >= self._size:
|
132
|
+
raise IndexError("list index out of range")
|
133
|
+
|
134
|
+
current = self._head.next
|
135
|
+
for _ in range(index):
|
136
|
+
current = current.next
|
137
|
+
return current.value
|
138
|
+
|
139
|
+
def set_at_index(self, index: int, value: Any) -> None:
|
140
|
+
"""Set element at index."""
|
141
|
+
if index < 0 or index >= self._size:
|
142
|
+
raise IndexError("list index out of range")
|
143
|
+
|
144
|
+
current = self._head.next
|
145
|
+
for _ in range(index):
|
146
|
+
current = current.next
|
147
|
+
current.value = value
|
148
|
+
|
149
|
+
# ============================================================================
|
150
|
+
# AUTO-3 Phase 1 methods
|
151
|
+
# ============================================================================
|
152
|
+
|
153
|
+
def as_linked_list(self):
|
154
|
+
"""Provide LinkedList behavioral view."""
|
155
|
+
return self
|
156
|
+
|
157
|
+
def as_stack(self):
|
158
|
+
"""Provide Stack behavioral view."""
|
159
|
+
# TODO: Implement Stack view
|
160
|
+
return self
|
161
|
+
|
162
|
+
def as_queue(self):
|
163
|
+
"""Provide Queue behavioral view."""
|
164
|
+
# TODO: Implement Queue view
|
165
|
+
return self
|
166
|
+
|
167
|
+
def as_deque(self):
|
168
|
+
"""Provide Deque behavioral view."""
|
169
|
+
# TODO: Implement Deque view
|
170
|
+
return self
|
171
|
+
|
172
|
+
# ============================================================================
|
173
|
+
# HELPER METHODS
|
174
|
+
# ============================================================================
|
175
|
+
|
176
|
+
def _insert_at_end(self, key: str, value: Any) -> None:
|
177
|
+
"""Insert new node at the end."""
|
178
|
+
self._insert_before(self._tail, key, value)
|
179
|
+
|
180
|
+
def _insert_after(self, node: ListNode, key: str, value: Any) -> None:
|
181
|
+
"""Insert new node after specified node."""
|
182
|
+
new_node = ListNode(key, value)
|
183
|
+
new_node.next = node.next
|
184
|
+
new_node.prev = node
|
185
|
+
node.next.prev = new_node
|
186
|
+
node.next = new_node
|
187
|
+
self._key_to_node[key] = new_node
|
188
|
+
self._size += 1
|
189
|
+
|
190
|
+
def _insert_before(self, node: ListNode, key: str, value: Any) -> None:
|
191
|
+
"""Insert new node before specified node."""
|
192
|
+
new_node = ListNode(key, value)
|
193
|
+
new_node.prev = node.prev
|
194
|
+
new_node.next = node
|
195
|
+
node.prev.next = new_node
|
196
|
+
node.prev = new_node
|
197
|
+
self._key_to_node[key] = new_node
|
198
|
+
self._size += 1
|
199
|
+
|
200
|
+
def _remove_node(self, node: ListNode) -> None:
|
201
|
+
"""Remove node from list."""
|
202
|
+
node.prev.next = node.next
|
203
|
+
node.next.prev = node.prev
|
204
|
+
self._size -= 1
|
205
|
+
|
206
|
+
# ============================================================================
|
207
|
+
# PERFORMANCE CHARACTERISTICS
|
208
|
+
# ============================================================================
|
209
|
+
|
210
|
+
@property
|
211
|
+
def backend_info(self) -> Dict[str, Any]:
|
212
|
+
"""Get backend implementation info."""
|
213
|
+
return {
|
214
|
+
'strategy': 'LINKED_LIST',
|
215
|
+
'backend': 'Doubly linked list',
|
216
|
+
'complexity': {
|
217
|
+
'get': 'O(n)',
|
218
|
+
'put': 'O(1)',
|
219
|
+
'insert': 'O(1) at known position',
|
220
|
+
'delete': 'O(1) at known position',
|
221
|
+
'search': 'O(n)'
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
@property
|
226
|
+
def metrics(self) -> Dict[str, Any]:
|
227
|
+
"""Get performance metrics."""
|
228
|
+
return {
|
229
|
+
'size': self._size,
|
230
|
+
'memory_usage': f"{self._size * 32} bytes (estimated)",
|
231
|
+
'doubly_linked': self.doubly_linked
|
232
|
+
}
|