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,387 @@
|
|
1
|
+
#exonware\xnode\strategies\impls\node_treap.py
|
2
|
+
"""
|
3
|
+
Treap Node Strategy Implementation
|
4
|
+
|
5
|
+
This module implements the TREAP strategy for randomized balanced trees
|
6
|
+
combining binary search tree and heap properties.
|
7
|
+
"""
|
8
|
+
|
9
|
+
import random
|
10
|
+
from typing import Any, Iterator, List, Dict, Optional, Tuple
|
11
|
+
from .base import ANodeTreeStrategy
|
12
|
+
from ...types import NodeMode, NodeTrait
|
13
|
+
|
14
|
+
|
15
|
+
class TreapNode:
|
16
|
+
"""Node in the treap."""
|
17
|
+
|
18
|
+
def __init__(self, key: str, value: Any = None, priority: int = None):
|
19
|
+
self.key = key
|
20
|
+
self.value = value
|
21
|
+
self.priority = priority if priority is not None else random.randint(1, 1000000)
|
22
|
+
self.left: Optional['TreapNode'] = None
|
23
|
+
self.right: Optional['TreapNode'] = None
|
24
|
+
self._hash = None
|
25
|
+
|
26
|
+
def __hash__(self) -> int:
|
27
|
+
"""Cache hash for performance."""
|
28
|
+
if self._hash is None:
|
29
|
+
self._hash = hash((self.key, self.value, self.priority))
|
30
|
+
return self._hash
|
31
|
+
|
32
|
+
def __eq__(self, other) -> bool:
|
33
|
+
"""Structural equality."""
|
34
|
+
if not isinstance(other, TreapNode):
|
35
|
+
return False
|
36
|
+
return (self.key == other.key and
|
37
|
+
self.value == other.value and
|
38
|
+
self.priority == other.priority)
|
39
|
+
|
40
|
+
|
41
|
+
class TreapStrategy(ANodeTreeStrategy):
|
42
|
+
"""
|
43
|
+
Treap node strategy for randomized balanced trees.
|
44
|
+
|
45
|
+
Combines binary search tree and heap properties with randomized
|
46
|
+
priorities for self-balancing behavior.
|
47
|
+
"""
|
48
|
+
|
49
|
+
def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
|
50
|
+
"""Initialize the treap strategy."""
|
51
|
+
super().__init__(NodeMode.TREAP, traits, **options)
|
52
|
+
|
53
|
+
self.case_sensitive = options.get('case_sensitive', True)
|
54
|
+
self.priority_range = options.get('priority_range', (1, 1000000))
|
55
|
+
|
56
|
+
# Core treap
|
57
|
+
self._root: Optional[TreapNode] = None
|
58
|
+
self._size = 0
|
59
|
+
|
60
|
+
# Statistics
|
61
|
+
self._total_insertions = 0
|
62
|
+
self._total_deletions = 0
|
63
|
+
self._total_rotations = 0
|
64
|
+
self._max_height = 0
|
65
|
+
|
66
|
+
def get_supported_traits(self) -> NodeTrait:
|
67
|
+
"""Get the traits supported by the treap strategy."""
|
68
|
+
return (NodeTrait.ORDERED | NodeTrait.INDEXED)
|
69
|
+
|
70
|
+
def _normalize_key(self, key: str) -> str:
|
71
|
+
"""Normalize key based on case sensitivity."""
|
72
|
+
return key if self.case_sensitive else key.lower()
|
73
|
+
|
74
|
+
def _get_height(self, node: Optional[TreapNode]) -> int:
|
75
|
+
"""Get height of node."""
|
76
|
+
if not node:
|
77
|
+
return 0
|
78
|
+
|
79
|
+
left_height = self._get_height(node.left)
|
80
|
+
right_height = self._get_height(node.right)
|
81
|
+
return 1 + max(left_height, right_height)
|
82
|
+
|
83
|
+
def _rotate_right(self, node: TreapNode) -> TreapNode:
|
84
|
+
"""Right rotation around node."""
|
85
|
+
left_child = node.left
|
86
|
+
if not left_child:
|
87
|
+
return node
|
88
|
+
|
89
|
+
# Perform rotation
|
90
|
+
node.left = left_child.right
|
91
|
+
left_child.right = node
|
92
|
+
|
93
|
+
self._total_rotations += 1
|
94
|
+
return left_child
|
95
|
+
|
96
|
+
def _rotate_left(self, node: TreapNode) -> TreapNode:
|
97
|
+
"""Left rotation around node."""
|
98
|
+
right_child = node.right
|
99
|
+
if not right_child:
|
100
|
+
return node
|
101
|
+
|
102
|
+
# Perform rotation
|
103
|
+
node.right = right_child.left
|
104
|
+
right_child.left = node
|
105
|
+
|
106
|
+
self._total_rotations += 1
|
107
|
+
return right_child
|
108
|
+
|
109
|
+
def _balance_treap(self, node: TreapNode) -> TreapNode:
|
110
|
+
"""Balance treap using heap property."""
|
111
|
+
# Rotate right if left child has higher priority
|
112
|
+
if node.left and node.left.priority > node.priority:
|
113
|
+
return self._rotate_right(node)
|
114
|
+
|
115
|
+
# Rotate left if right child has higher priority
|
116
|
+
if node.right and node.right.priority > node.priority:
|
117
|
+
return self._rotate_left(node)
|
118
|
+
|
119
|
+
return node
|
120
|
+
|
121
|
+
def _insert_node(self, node: Optional[TreapNode], key: str, value: Any, priority: int = None) -> Tuple[TreapNode, bool]:
|
122
|
+
"""Insert node with given key and value."""
|
123
|
+
if not node:
|
124
|
+
new_node = TreapNode(key, value, priority)
|
125
|
+
return new_node, True
|
126
|
+
|
127
|
+
normalized_key = self._normalize_key(key)
|
128
|
+
node_key = self._normalize_key(node.key)
|
129
|
+
|
130
|
+
if normalized_key < node_key:
|
131
|
+
node.left, inserted = self._insert_node(node.left, key, value, priority)
|
132
|
+
elif normalized_key > node_key:
|
133
|
+
node.right, inserted = self._insert_node(node.right, key, value, priority)
|
134
|
+
else:
|
135
|
+
# Key already exists, update value
|
136
|
+
node.value = value
|
137
|
+
return node, False
|
138
|
+
|
139
|
+
if not inserted:
|
140
|
+
return node, False
|
141
|
+
|
142
|
+
# Balance treap using heap property
|
143
|
+
balanced_node = self._balance_treap(node)
|
144
|
+
return balanced_node, True
|
145
|
+
|
146
|
+
def _find_node(self, node: Optional[TreapNode], key: str) -> Optional[TreapNode]:
|
147
|
+
"""Find node with given key."""
|
148
|
+
if not node:
|
149
|
+
return None
|
150
|
+
|
151
|
+
normalized_key = self._normalize_key(key)
|
152
|
+
node_key = self._normalize_key(node.key)
|
153
|
+
|
154
|
+
if normalized_key < node_key:
|
155
|
+
return self._find_node(node.left, key)
|
156
|
+
elif normalized_key > node_key:
|
157
|
+
return self._find_node(node.right, key)
|
158
|
+
else:
|
159
|
+
return node
|
160
|
+
|
161
|
+
def _find_min(self, node: TreapNode) -> TreapNode:
|
162
|
+
"""Find minimum node in subtree."""
|
163
|
+
while node.left:
|
164
|
+
node = node.left
|
165
|
+
return node
|
166
|
+
|
167
|
+
def _find_max(self, node: TreapNode) -> TreapNode:
|
168
|
+
"""Find maximum node in subtree."""
|
169
|
+
while node.right:
|
170
|
+
node = node.right
|
171
|
+
return node
|
172
|
+
|
173
|
+
def _delete_node(self, node: Optional[TreapNode], key: str) -> Tuple[Optional[TreapNode], bool]:
|
174
|
+
"""Delete node with given key."""
|
175
|
+
if not node:
|
176
|
+
return None, False
|
177
|
+
|
178
|
+
normalized_key = self._normalize_key(key)
|
179
|
+
node_key = self._normalize_key(node.key)
|
180
|
+
|
181
|
+
if normalized_key < node_key:
|
182
|
+
node.left, deleted = self._delete_node(node.left, key)
|
183
|
+
elif normalized_key > node_key:
|
184
|
+
node.right, deleted = self._delete_node(node.right, key)
|
185
|
+
else:
|
186
|
+
# Found node to delete
|
187
|
+
if not node.left:
|
188
|
+
return node.right, True
|
189
|
+
elif not node.right:
|
190
|
+
return node.left, True
|
191
|
+
else:
|
192
|
+
# Node has both children, rotate to leaf
|
193
|
+
if node.left.priority > node.right.priority:
|
194
|
+
node = self._rotate_right(node)
|
195
|
+
node.right, _ = self._delete_node(node.right, key)
|
196
|
+
else:
|
197
|
+
node = self._rotate_left(node)
|
198
|
+
node.left, _ = self._delete_node(node.left, key)
|
199
|
+
deleted = True
|
200
|
+
|
201
|
+
if not deleted:
|
202
|
+
return node, False
|
203
|
+
|
204
|
+
return node, True
|
205
|
+
|
206
|
+
def _inorder_traversal(self, node: Optional[TreapNode]) -> Iterator[Tuple[str, Any]]:
|
207
|
+
"""In-order traversal of tree."""
|
208
|
+
if node:
|
209
|
+
yield from self._inorder_traversal(node.left)
|
210
|
+
yield (node.key, node.value)
|
211
|
+
yield from self._inorder_traversal(node.right)
|
212
|
+
|
213
|
+
# ============================================================================
|
214
|
+
# CORE OPERATIONS
|
215
|
+
# ============================================================================
|
216
|
+
|
217
|
+
def put(self, key: Any, value: Any = None) -> None:
|
218
|
+
"""Store a key-value pair."""
|
219
|
+
if not isinstance(key, str):
|
220
|
+
key = str(key)
|
221
|
+
|
222
|
+
# Generate random priority
|
223
|
+
priority = random.randint(self.priority_range[0], self.priority_range[1])
|
224
|
+
self._root, inserted = self._insert_node(self._root, key, value, priority)
|
225
|
+
if inserted:
|
226
|
+
self._size += 1
|
227
|
+
self._total_insertions += 1
|
228
|
+
self._max_height = max(self._max_height, self._get_height(self._root))
|
229
|
+
|
230
|
+
def get(self, key: Any, default: Any = None) -> Any:
|
231
|
+
"""Retrieve a value by key."""
|
232
|
+
if not isinstance(key, str):
|
233
|
+
key = str(key)
|
234
|
+
|
235
|
+
node = self._find_node(self._root, key)
|
236
|
+
return node.value if node else default
|
237
|
+
|
238
|
+
def delete(self, key: Any) -> bool:
|
239
|
+
"""Remove a key-value pair."""
|
240
|
+
if not isinstance(key, str):
|
241
|
+
key = str(key)
|
242
|
+
|
243
|
+
self._root, deleted = self._delete_node(self._root, key)
|
244
|
+
if deleted:
|
245
|
+
self._size -= 1
|
246
|
+
self._total_deletions += 1
|
247
|
+
return deleted
|
248
|
+
|
249
|
+
def has(self, key: Any) -> bool:
|
250
|
+
"""Check if key exists."""
|
251
|
+
if not isinstance(key, str):
|
252
|
+
key = str(key)
|
253
|
+
|
254
|
+
return self._find_node(self._root, key) is not None
|
255
|
+
|
256
|
+
def clear(self) -> None:
|
257
|
+
"""Clear all data."""
|
258
|
+
self._root = None
|
259
|
+
self._size = 0
|
260
|
+
|
261
|
+
def size(self) -> int:
|
262
|
+
"""Get number of key-value pairs."""
|
263
|
+
return self._size
|
264
|
+
|
265
|
+
def is_empty(self) -> bool:
|
266
|
+
"""Check if tree is empty."""
|
267
|
+
return self._root is None
|
268
|
+
|
269
|
+
# ============================================================================
|
270
|
+
# ITERATION
|
271
|
+
# ============================================================================
|
272
|
+
|
273
|
+
def keys(self) -> Iterator[str]:
|
274
|
+
"""Iterate over keys in sorted order."""
|
275
|
+
for key, _ in self._inorder_traversal(self._root):
|
276
|
+
yield key
|
277
|
+
|
278
|
+
def values(self) -> Iterator[Any]:
|
279
|
+
"""Iterate over values in key order."""
|
280
|
+
for _, value in self._inorder_traversal(self._root):
|
281
|
+
yield value
|
282
|
+
|
283
|
+
def items(self) -> Iterator[Tuple[str, Any]]:
|
284
|
+
"""Iterate over key-value pairs in sorted order."""
|
285
|
+
yield from self._inorder_traversal(self._root)
|
286
|
+
|
287
|
+
def __iter__(self) -> Iterator[str]:
|
288
|
+
"""Iterate over keys."""
|
289
|
+
yield from self.keys()
|
290
|
+
|
291
|
+
# ============================================================================
|
292
|
+
# TREAP SPECIFIC OPERATIONS
|
293
|
+
# ============================================================================
|
294
|
+
|
295
|
+
def get_min(self) -> Optional[Tuple[str, Any]]:
|
296
|
+
"""Get the minimum key-value pair."""
|
297
|
+
if not self._root:
|
298
|
+
return None
|
299
|
+
|
300
|
+
min_node = self._find_min(self._root)
|
301
|
+
return (min_node.key, min_node.value)
|
302
|
+
|
303
|
+
def get_max(self) -> Optional[Tuple[str, Any]]:
|
304
|
+
"""Get the maximum key-value pair."""
|
305
|
+
if not self._root:
|
306
|
+
return None
|
307
|
+
|
308
|
+
max_node = self._find_max(self._root)
|
309
|
+
return (max_node.key, max_node.value)
|
310
|
+
|
311
|
+
def get_height(self) -> int:
|
312
|
+
"""Get the height of the tree."""
|
313
|
+
return self._get_height(self._root)
|
314
|
+
|
315
|
+
def get_priority(self, key: str) -> Optional[int]:
|
316
|
+
"""Get priority of node with given key."""
|
317
|
+
node = self._find_node(self._root, key)
|
318
|
+
return node.priority if node else None
|
319
|
+
|
320
|
+
def set_priority(self, key: str, priority: int) -> bool:
|
321
|
+
"""Set priority of node with given key."""
|
322
|
+
node = self._find_node(self._root, key)
|
323
|
+
if not node:
|
324
|
+
return False
|
325
|
+
|
326
|
+
node.priority = priority
|
327
|
+
# Rebalance if necessary
|
328
|
+
self._root = self._balance_treap(self._root)
|
329
|
+
return True
|
330
|
+
|
331
|
+
def get_max_priority(self) -> Optional[Tuple[str, Any, int]]:
|
332
|
+
"""Get node with maximum priority."""
|
333
|
+
if not self._root:
|
334
|
+
return None
|
335
|
+
|
336
|
+
def find_max_priority(node: TreapNode) -> TreapNode:
|
337
|
+
max_node = node
|
338
|
+
if node.left:
|
339
|
+
left_max = find_max_priority(node.left)
|
340
|
+
if left_max.priority > max_node.priority:
|
341
|
+
max_node = left_max
|
342
|
+
if node.right:
|
343
|
+
right_max = find_max_priority(node.right)
|
344
|
+
if right_max.priority > max_node.priority:
|
345
|
+
max_node = right_max
|
346
|
+
return max_node
|
347
|
+
|
348
|
+
max_node = find_max_priority(self._root)
|
349
|
+
return (max_node.key, max_node.value, max_node.priority)
|
350
|
+
|
351
|
+
def is_treap_valid(self) -> bool:
|
352
|
+
"""Check if tree satisfies treap properties."""
|
353
|
+
def check_treap(node: Optional[TreapNode]) -> bool:
|
354
|
+
if not node:
|
355
|
+
return True
|
356
|
+
|
357
|
+
# Check heap property
|
358
|
+
if node.left and node.left.priority > node.priority:
|
359
|
+
return False
|
360
|
+
if node.right and node.right.priority > node.priority:
|
361
|
+
return False
|
362
|
+
|
363
|
+
# Check BST property
|
364
|
+
if node.left and self._normalize_key(node.left.key) >= self._normalize_key(node.key):
|
365
|
+
return False
|
366
|
+
if node.right and self._normalize_key(node.right.key) <= self._normalize_key(node.key):
|
367
|
+
return False
|
368
|
+
|
369
|
+
return check_treap(node.left) and check_treap(node.right)
|
370
|
+
|
371
|
+
return check_treap(self._root)
|
372
|
+
|
373
|
+
def get_stats(self) -> Dict[str, Any]:
|
374
|
+
"""Get performance statistics."""
|
375
|
+
return {
|
376
|
+
'size': self._size,
|
377
|
+
'height': self._get_height(self._root),
|
378
|
+
'max_height': self._max_height,
|
379
|
+
'total_insertions': self._total_insertions,
|
380
|
+
'total_deletions': self._total_deletions,
|
381
|
+
'total_rotations': self._total_rotations,
|
382
|
+
'priority_range': self.priority_range,
|
383
|
+
'is_treap_valid': self.is_treap_valid(),
|
384
|
+
'strategy': 'TREAP',
|
385
|
+
'backend': 'Randomized treap with heap and BST properties',
|
386
|
+
'traits': [trait.name for trait in NodeTrait if self.has_trait(trait)]
|
387
|
+
}
|