exonware-xwnode 0.0.1.21__py3-none-any.whl → 0.0.1.23__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 +8 -1
- exonware/xwnode/__init__.py +18 -5
- exonware/xwnode/add_strategy_types.py +165 -0
- exonware/xwnode/base.py +7 -5
- exonware/xwnode/common/__init__.py +1 -1
- exonware/xwnode/common/graph/__init__.py +30 -0
- exonware/xwnode/common/graph/caching.py +131 -0
- exonware/xwnode/common/graph/contracts.py +100 -0
- exonware/xwnode/common/graph/errors.py +44 -0
- exonware/xwnode/common/graph/indexing.py +260 -0
- exonware/xwnode/common/graph/manager.py +568 -0
- exonware/xwnode/common/management/__init__.py +3 -5
- exonware/xwnode/common/management/manager.py +9 -9
- exonware/xwnode/common/management/migration.py +6 -6
- exonware/xwnode/common/monitoring/__init__.py +3 -5
- exonware/xwnode/common/monitoring/metrics.py +7 -3
- exonware/xwnode/common/monitoring/pattern_detector.py +2 -2
- exonware/xwnode/common/monitoring/performance_monitor.py +6 -2
- exonware/xwnode/common/patterns/__init__.py +3 -5
- exonware/xwnode/common/patterns/advisor.py +1 -1
- exonware/xwnode/common/patterns/flyweight.py +6 -2
- exonware/xwnode/common/patterns/registry.py +203 -184
- exonware/xwnode/common/utils/__init__.py +25 -11
- exonware/xwnode/common/utils/simple.py +1 -1
- exonware/xwnode/config.py +3 -8
- exonware/xwnode/contracts.py +4 -105
- exonware/xwnode/defs.py +413 -159
- exonware/xwnode/edges/strategies/__init__.py +86 -4
- exonware/xwnode/edges/strategies/_base_edge.py +2 -2
- exonware/xwnode/edges/strategies/adj_list.py +287 -121
- exonware/xwnode/edges/strategies/adj_matrix.py +316 -222
- exonware/xwnode/edges/strategies/base.py +1 -1
- exonware/xwnode/edges/strategies/{edge_bidir_wrapper.py → bidir_wrapper.py} +45 -4
- exonware/xwnode/edges/strategies/bitemporal.py +520 -0
- exonware/xwnode/edges/strategies/{edge_block_adj_matrix.py → block_adj_matrix.py} +77 -6
- exonware/xwnode/edges/strategies/bv_graph.py +664 -0
- exonware/xwnode/edges/strategies/compressed_graph.py +217 -0
- exonware/xwnode/edges/strategies/{edge_coo.py → coo.py} +46 -4
- exonware/xwnode/edges/strategies/{edge_csc.py → csc.py} +45 -4
- exonware/xwnode/edges/strategies/{edge_csr.py → csr.py} +94 -12
- exonware/xwnode/edges/strategies/{edge_dynamic_adj_list.py → dynamic_adj_list.py} +46 -4
- exonware/xwnode/edges/strategies/edge_list.py +168 -0
- exonware/xwnode/edges/strategies/edge_property_store.py +2 -2
- exonware/xwnode/edges/strategies/euler_tour.py +560 -0
- exonware/xwnode/edges/strategies/{edge_flow_network.py → flow_network.py} +2 -2
- exonware/xwnode/edges/strategies/graphblas.py +449 -0
- exonware/xwnode/edges/strategies/hnsw.py +637 -0
- exonware/xwnode/edges/strategies/hop2_labels.py +467 -0
- exonware/xwnode/edges/strategies/{edge_hyperedge_set.py → hyperedge_set.py} +2 -2
- exonware/xwnode/edges/strategies/incidence_matrix.py +250 -0
- exonware/xwnode/edges/strategies/k2_tree.py +613 -0
- exonware/xwnode/edges/strategies/link_cut.py +626 -0
- exonware/xwnode/edges/strategies/multiplex.py +532 -0
- exonware/xwnode/edges/strategies/{edge_neural_graph.py → neural_graph.py} +2 -2
- exonware/xwnode/edges/strategies/{edge_octree.py → octree.py} +69 -11
- exonware/xwnode/edges/strategies/{edge_quadtree.py → quadtree.py} +66 -10
- exonware/xwnode/edges/strategies/roaring_adj.py +438 -0
- exonware/xwnode/edges/strategies/{edge_rtree.py → rtree.py} +43 -5
- exonware/xwnode/edges/strategies/{edge_temporal_edgeset.py → temporal_edgeset.py} +24 -5
- exonware/xwnode/edges/strategies/{edge_tree_graph_basic.py → tree_graph_basic.py} +78 -7
- exonware/xwnode/edges/strategies/{edge_weighted_graph.py → weighted_graph.py} +188 -10
- exonware/xwnode/errors.py +3 -6
- exonware/xwnode/facade.py +20 -20
- exonware/xwnode/nodes/strategies/__init__.py +29 -9
- exonware/xwnode/nodes/strategies/adjacency_list.py +650 -177
- exonware/xwnode/nodes/strategies/aho_corasick.py +358 -183
- exonware/xwnode/nodes/strategies/array_list.py +36 -3
- exonware/xwnode/nodes/strategies/art.py +581 -0
- exonware/xwnode/nodes/strategies/{node_avl_tree.py → avl_tree.py} +77 -6
- exonware/xwnode/nodes/strategies/{node_b_plus_tree.py → b_plus_tree.py} +81 -40
- exonware/xwnode/nodes/strategies/{node_btree.py → b_tree.py} +79 -9
- exonware/xwnode/nodes/strategies/base.py +469 -98
- exonware/xwnode/nodes/strategies/{node_bitmap.py → bitmap.py} +12 -12
- exonware/xwnode/nodes/strategies/{node_bitset_dynamic.py → bitset_dynamic.py} +11 -11
- exonware/xwnode/nodes/strategies/{node_bloom_filter.py → bloom_filter.py} +15 -2
- exonware/xwnode/nodes/strategies/bloomier_filter.py +519 -0
- exonware/xwnode/nodes/strategies/bw_tree.py +531 -0
- exonware/xwnode/nodes/strategies/contracts.py +1 -1
- exonware/xwnode/nodes/strategies/{node_count_min_sketch.py → count_min_sketch.py} +3 -2
- exonware/xwnode/nodes/strategies/{node_cow_tree.py → cow_tree.py} +135 -13
- exonware/xwnode/nodes/strategies/crdt_map.py +629 -0
- exonware/xwnode/nodes/strategies/{node_cuckoo_hash.py → cuckoo_hash.py} +2 -2
- exonware/xwnode/nodes/strategies/{node_xdata_optimized.py → data_interchange_optimized.py} +21 -4
- exonware/xwnode/nodes/strategies/dawg.py +876 -0
- exonware/xwnode/nodes/strategies/deque.py +321 -153
- exonware/xwnode/nodes/strategies/extendible_hash.py +93 -0
- exonware/xwnode/nodes/strategies/{node_fenwick_tree.py → fenwick_tree.py} +111 -19
- exonware/xwnode/nodes/strategies/hamt.py +403 -0
- exonware/xwnode/nodes/strategies/hash_map.py +354 -67
- exonware/xwnode/nodes/strategies/heap.py +105 -5
- exonware/xwnode/nodes/strategies/hopscotch_hash.py +525 -0
- exonware/xwnode/nodes/strategies/{node_hyperloglog.py → hyperloglog.py} +6 -5
- exonware/xwnode/nodes/strategies/interval_tree.py +742 -0
- exonware/xwnode/nodes/strategies/kd_tree.py +703 -0
- exonware/xwnode/nodes/strategies/learned_index.py +533 -0
- exonware/xwnode/nodes/strategies/linear_hash.py +93 -0
- exonware/xwnode/nodes/strategies/linked_list.py +316 -119
- exonware/xwnode/nodes/strategies/{node_lsm_tree.py → lsm_tree.py} +219 -15
- exonware/xwnode/nodes/strategies/masstree.py +130 -0
- exonware/xwnode/nodes/strategies/{node_persistent_tree.py → persistent_tree.py} +149 -9
- exonware/xwnode/nodes/strategies/priority_queue.py +544 -132
- exonware/xwnode/nodes/strategies/queue.py +249 -120
- exonware/xwnode/nodes/strategies/{node_red_black_tree.py → red_black_tree.py} +183 -72
- exonware/xwnode/nodes/strategies/{node_roaring_bitmap.py → roaring_bitmap.py} +19 -6
- exonware/xwnode/nodes/strategies/rope.py +717 -0
- exonware/xwnode/nodes/strategies/{node_segment_tree.py → segment_tree.py} +106 -106
- exonware/xwnode/nodes/strategies/{node_set_hash.py → set_hash.py} +30 -29
- exonware/xwnode/nodes/strategies/{node_skip_list.py → skip_list.py} +74 -6
- exonware/xwnode/nodes/strategies/sparse_matrix.py +427 -131
- exonware/xwnode/nodes/strategies/{node_splay_tree.py → splay_tree.py} +55 -6
- exonware/xwnode/nodes/strategies/stack.py +244 -112
- exonware/xwnode/nodes/strategies/{node_suffix_array.py → suffix_array.py} +5 -1
- exonware/xwnode/nodes/strategies/t_tree.py +94 -0
- exonware/xwnode/nodes/strategies/{node_treap.py → treap.py} +75 -6
- exonware/xwnode/nodes/strategies/{node_tree_graph_hybrid.py → tree_graph_hybrid.py} +46 -5
- exonware/xwnode/nodes/strategies/trie.py +153 -9
- exonware/xwnode/nodes/strategies/union_find.py +111 -5
- exonware/xwnode/nodes/strategies/veb_tree.py +856 -0
- exonware/xwnode/strategies/__init__.py +5 -51
- exonware/xwnode/version.py +3 -3
- {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/METADATA +23 -3
- exonware_xwnode-0.0.1.23.dist-info/RECORD +130 -0
- exonware/xwnode/edges/strategies/edge_adj_list.py +0 -353
- exonware/xwnode/edges/strategies/edge_adj_matrix.py +0 -445
- exonware/xwnode/nodes/strategies/_base_node.py +0 -307
- exonware/xwnode/nodes/strategies/node_aho_corasick.py +0 -525
- exonware/xwnode/nodes/strategies/node_array_list.py +0 -179
- exonware/xwnode/nodes/strategies/node_hash_map.py +0 -273
- exonware/xwnode/nodes/strategies/node_heap.py +0 -196
- exonware/xwnode/nodes/strategies/node_linked_list.py +0 -413
- exonware/xwnode/nodes/strategies/node_trie.py +0 -257
- exonware/xwnode/nodes/strategies/node_union_find.py +0 -192
- exonware/xwnode/queries/executors/__init__.py +0 -47
- exonware/xwnode/queries/executors/advanced/__init__.py +0 -37
- exonware/xwnode/queries/executors/advanced/aggregate_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/ask_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/construct_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/describe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/for_loop_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/foreach_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/join_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/let_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/mutation_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/options_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/pipe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/subscribe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/subscription_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/union_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/window_executor.py +0 -51
- exonware/xwnode/queries/executors/advanced/with_cte_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/__init__.py +0 -21
- exonware/xwnode/queries/executors/aggregation/avg_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/count_executor.py +0 -38
- exonware/xwnode/queries/executors/aggregation/distinct_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/group_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/having_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/max_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/min_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/sum_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/summarize_executor.py +0 -50
- exonware/xwnode/queries/executors/array/__init__.py +0 -9
- exonware/xwnode/queries/executors/array/indexing_executor.py +0 -51
- exonware/xwnode/queries/executors/array/slicing_executor.py +0 -51
- exonware/xwnode/queries/executors/base.py +0 -257
- exonware/xwnode/queries/executors/capability_checker.py +0 -204
- exonware/xwnode/queries/executors/contracts.py +0 -166
- exonware/xwnode/queries/executors/core/__init__.py +0 -17
- exonware/xwnode/queries/executors/core/create_executor.py +0 -96
- exonware/xwnode/queries/executors/core/delete_executor.py +0 -99
- exonware/xwnode/queries/executors/core/drop_executor.py +0 -100
- exonware/xwnode/queries/executors/core/insert_executor.py +0 -39
- exonware/xwnode/queries/executors/core/select_executor.py +0 -152
- exonware/xwnode/queries/executors/core/update_executor.py +0 -102
- exonware/xwnode/queries/executors/data/__init__.py +0 -13
- exonware/xwnode/queries/executors/data/alter_executor.py +0 -50
- exonware/xwnode/queries/executors/data/load_executor.py +0 -50
- exonware/xwnode/queries/executors/data/merge_executor.py +0 -50
- exonware/xwnode/queries/executors/data/store_executor.py +0 -50
- exonware/xwnode/queries/executors/defs.py +0 -93
- exonware/xwnode/queries/executors/engine.py +0 -221
- exonware/xwnode/queries/executors/errors.py +0 -68
- exonware/xwnode/queries/executors/filtering/__init__.py +0 -25
- exonware/xwnode/queries/executors/filtering/between_executor.py +0 -80
- exonware/xwnode/queries/executors/filtering/filter_executor.py +0 -79
- exonware/xwnode/queries/executors/filtering/has_executor.py +0 -70
- exonware/xwnode/queries/executors/filtering/in_executor.py +0 -70
- exonware/xwnode/queries/executors/filtering/like_executor.py +0 -76
- exonware/xwnode/queries/executors/filtering/optional_executor.py +0 -76
- exonware/xwnode/queries/executors/filtering/range_executor.py +0 -80
- exonware/xwnode/queries/executors/filtering/term_executor.py +0 -77
- exonware/xwnode/queries/executors/filtering/values_executor.py +0 -71
- exonware/xwnode/queries/executors/filtering/where_executor.py +0 -44
- exonware/xwnode/queries/executors/graph/__init__.py +0 -15
- exonware/xwnode/queries/executors/graph/in_traverse_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/match_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/out_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/path_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/return_executor.py +0 -51
- exonware/xwnode/queries/executors/ordering/__init__.py +0 -9
- exonware/xwnode/queries/executors/ordering/by_executor.py +0 -50
- exonware/xwnode/queries/executors/ordering/order_executor.py +0 -51
- exonware/xwnode/queries/executors/projection/__init__.py +0 -9
- exonware/xwnode/queries/executors/projection/extend_executor.py +0 -50
- exonware/xwnode/queries/executors/projection/project_executor.py +0 -50
- exonware/xwnode/queries/executors/registry.py +0 -173
- exonware/xwnode/queries/parsers/__init__.py +0 -26
- exonware/xwnode/queries/parsers/base.py +0 -86
- exonware/xwnode/queries/parsers/contracts.py +0 -46
- exonware/xwnode/queries/parsers/errors.py +0 -53
- exonware/xwnode/queries/parsers/sql_param_extractor.py +0 -318
- exonware/xwnode/queries/strategies/__init__.py +0 -24
- exonware/xwnode/queries/strategies/base.py +0 -236
- exonware/xwnode/queries/strategies/cql.py +0 -201
- exonware/xwnode/queries/strategies/cypher.py +0 -181
- exonware/xwnode/queries/strategies/datalog.py +0 -70
- exonware/xwnode/queries/strategies/elastic_dsl.py +0 -70
- exonware/xwnode/queries/strategies/eql.py +0 -70
- exonware/xwnode/queries/strategies/flux.py +0 -70
- exonware/xwnode/queries/strategies/gql.py +0 -70
- exonware/xwnode/queries/strategies/graphql.py +0 -240
- exonware/xwnode/queries/strategies/gremlin.py +0 -181
- exonware/xwnode/queries/strategies/hiveql.py +0 -214
- exonware/xwnode/queries/strategies/hql.py +0 -70
- exonware/xwnode/queries/strategies/jmespath.py +0 -219
- exonware/xwnode/queries/strategies/jq.py +0 -66
- exonware/xwnode/queries/strategies/json_query.py +0 -66
- exonware/xwnode/queries/strategies/jsoniq.py +0 -248
- exonware/xwnode/queries/strategies/kql.py +0 -70
- exonware/xwnode/queries/strategies/linq.py +0 -238
- exonware/xwnode/queries/strategies/logql.py +0 -70
- exonware/xwnode/queries/strategies/mql.py +0 -68
- exonware/xwnode/queries/strategies/n1ql.py +0 -210
- exonware/xwnode/queries/strategies/partiql.py +0 -70
- exonware/xwnode/queries/strategies/pig.py +0 -215
- exonware/xwnode/queries/strategies/promql.py +0 -70
- exonware/xwnode/queries/strategies/sparql.py +0 -220
- exonware/xwnode/queries/strategies/sql.py +0 -275
- exonware/xwnode/queries/strategies/xml_query.py +0 -66
- exonware/xwnode/queries/strategies/xpath.py +0 -223
- exonware/xwnode/queries/strategies/xquery.py +0 -258
- exonware/xwnode/queries/strategies/xwnode_executor.py +0 -332
- exonware/xwnode/queries/strategies/xwquery.py +0 -456
- exonware_xwnode-0.0.1.21.dist-info/RECORD +0 -214
- /exonware/xwnode/nodes/strategies/{node_ordered_map.py → ordered_map.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_ordered_map_balanced.py → ordered_map_balanced.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_patricia.py → patricia.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_radix_trie.py → radix_trie.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_set_tree.py → set_tree.py} +0 -0
- {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/WHEEL +0 -0
- {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/licenses/LICENSE +0 -0
@@ -1,16 +1,25 @@
|
|
1
1
|
"""
|
2
|
+
#exonware/xwnode/src/exonware/xwnode/nodes/strategies/priority_queue.py
|
3
|
+
|
2
4
|
Priority Queue Strategy Implementation
|
3
5
|
|
4
|
-
|
6
|
+
Production-grade priority queue using binary heap.
|
7
|
+
|
8
|
+
Best Practices Implemented:
|
9
|
+
- Min-heap by default (heapq standard)
|
10
|
+
- Stable sorting with counter for equal priorities
|
11
|
+
- Efficient O(log n) operations
|
12
|
+
- Support for both min and max heaps
|
13
|
+
- Proper heap semantics following CLRS and industry standards
|
5
14
|
|
6
15
|
Company: eXonware.com
|
7
16
|
Author: Eng. Muhammad AlShehri
|
8
17
|
Email: connect@exonware.com
|
9
|
-
Version: 0.0.1.
|
10
|
-
Generation Date:
|
18
|
+
Version: 0.0.1.23
|
19
|
+
Generation Date: October 12, 2025
|
11
20
|
"""
|
12
21
|
|
13
|
-
from typing import Any, Iterator, Optional, Dict,
|
22
|
+
from typing import Any, Iterator, List, Optional, Dict, Tuple
|
14
23
|
import heapq
|
15
24
|
from .base import ANodeLinearStrategy
|
16
25
|
from .contracts import NodeType
|
@@ -19,44 +28,272 @@ from ...defs import NodeMode, NodeTrait
|
|
19
28
|
|
20
29
|
class PriorityQueueStrategy(ANodeLinearStrategy):
|
21
30
|
"""
|
22
|
-
Priority Queue node strategy
|
31
|
+
Production-grade Priority Queue node strategy.
|
32
|
+
|
33
|
+
Optimized for:
|
34
|
+
- Dijkstra's shortest path algorithm
|
35
|
+
- A* pathfinding
|
36
|
+
- Task scheduling with priorities
|
37
|
+
- Event simulation (discrete event systems)
|
38
|
+
- Median maintenance (with dual-heap pattern)
|
39
|
+
- Huffman coding
|
40
|
+
|
41
|
+
Performance:
|
42
|
+
- Insert: O(log n)
|
43
|
+
- Extract-Min: O(log n)
|
44
|
+
- Peek-Min: O(1)
|
45
|
+
- Decrease-Key: O(n) - requires linear search
|
46
|
+
- Build-Heap: O(n)
|
47
|
+
|
48
|
+
Security:
|
49
|
+
- Bounds checking on all operations
|
50
|
+
- Safe empty heap handling
|
51
|
+
- Priority validation
|
23
52
|
|
24
|
-
|
25
|
-
|
53
|
+
Implementation Details:
|
54
|
+
- Uses min-heap by default (lowest priority value = highest priority)
|
55
|
+
- Stable sorting via counter for equal priorities (FIFO for same priority)
|
56
|
+
- Tuple format: (priority, counter, value)
|
57
|
+
|
58
|
+
Follows eXonware Priorities:
|
59
|
+
1. Security: Input validation, safe operations
|
60
|
+
2. Usability: Standard priority queue interface
|
61
|
+
3. Maintainability: Clean heap implementation
|
62
|
+
4. Performance: O(log n) operations, O(1) peek
|
63
|
+
5. Extensibility: Support for custom priority types
|
64
|
+
"""
|
26
65
|
|
27
66
|
# Strategy type classification
|
28
67
|
STRATEGY_TYPE = NodeType.LINEAR
|
29
|
-
orithms like Dijkstra's.
|
30
|
-
"""
|
31
68
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
69
|
+
__slots__ = ('_heap', '_counter', '_max_size', '_is_max_heap')
|
70
|
+
|
71
|
+
def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
|
72
|
+
"""
|
73
|
+
Initialize an empty priority queue.
|
74
|
+
|
75
|
+
Args:
|
76
|
+
traits: Additional node traits
|
77
|
+
**options:
|
78
|
+
max_size: Optional maximum heap size
|
79
|
+
is_max_heap: True for max-heap, False for min-heap (default)
|
80
|
+
initial_items: Optional list of (priority, value) tuples
|
81
|
+
"""
|
82
|
+
super().__init__(
|
83
|
+
NodeMode.PRIORITY_QUEUE,
|
84
|
+
traits | NodeTrait.PRIORITY | NodeTrait.FAST_INSERT | NodeTrait.HEAP_OPERATIONS,
|
85
|
+
**options
|
86
|
+
)
|
87
|
+
self._max_size: Optional[int] = options.get('max_size')
|
88
|
+
self._is_max_heap: bool = options.get('is_max_heap', False)
|
89
|
+
self._heap: List[Tuple[float, int, Any]] = [] # (priority, counter, value)
|
90
|
+
self._counter = 0
|
91
|
+
|
92
|
+
# Build heap from initial items if provided
|
93
|
+
initial_items = options.get('initial_items', [])
|
94
|
+
if initial_items:
|
95
|
+
for priority, value in initial_items:
|
96
|
+
self.push(value, priority)
|
97
|
+
|
98
|
+
def get_supported_traits(self) -> NodeTrait:
|
99
|
+
"""Get the traits supported by the priority queue strategy."""
|
100
|
+
return NodeTrait.PRIORITY | NodeTrait.FAST_INSERT | NodeTrait.HEAP_OPERATIONS
|
101
|
+
|
102
|
+
# ============================================================================
|
103
|
+
# CORE PRIORITY QUEUE OPERATIONS (Industry Standard)
|
104
|
+
# ============================================================================
|
105
|
+
|
106
|
+
def push(self, value: Any, priority: float = 0.0) -> None:
|
107
|
+
"""
|
108
|
+
Insert a value with given priority.
|
109
|
+
|
110
|
+
Time: O(log n)
|
111
|
+
Space: O(1)
|
112
|
+
|
113
|
+
Args:
|
114
|
+
value: The value to insert
|
115
|
+
priority: Priority value (lower = higher priority for min-heap)
|
116
|
+
|
117
|
+
Raises:
|
118
|
+
OverflowError: If max_size is set and heap is full
|
119
|
+
"""
|
120
|
+
if self._max_size and len(self._heap) >= self._max_size:
|
121
|
+
raise OverflowError(f"Priority queue overflow: max size {self._max_size} reached")
|
122
|
+
|
123
|
+
# For max-heap, negate the priority
|
124
|
+
actual_priority = -priority if self._is_max_heap else priority
|
125
|
+
|
126
|
+
heapq.heappush(self._heap, (actual_priority, self._counter, value))
|
127
|
+
self._counter += 1
|
128
|
+
|
129
|
+
def pop(self) -> Any:
|
130
|
+
"""
|
131
|
+
Extract and return the highest priority item.
|
132
|
+
|
133
|
+
Time: O(log n)
|
134
|
+
Space: O(1)
|
135
|
+
|
136
|
+
Returns:
|
137
|
+
The highest priority value
|
138
|
+
|
139
|
+
Raises:
|
140
|
+
IndexError: If heap is empty
|
141
|
+
"""
|
142
|
+
if self.is_empty():
|
143
|
+
raise IndexError("pop from empty priority queue")
|
144
|
+
|
145
|
+
priority, counter, value = heapq.heappop(self._heap)
|
146
|
+
return value
|
147
|
+
|
148
|
+
def peek(self) -> Any:
|
149
|
+
"""
|
150
|
+
Peek at the highest priority item without removing it.
|
151
|
+
|
152
|
+
Time: O(1)
|
153
|
+
Space: O(1)
|
154
|
+
|
155
|
+
Returns:
|
156
|
+
The highest priority value
|
157
|
+
|
158
|
+
Raises:
|
159
|
+
IndexError: If heap is empty
|
160
|
+
"""
|
161
|
+
if self.is_empty():
|
162
|
+
raise IndexError("peek from empty priority queue")
|
163
|
+
|
164
|
+
return self._heap[0][2] # Return value from (priority, counter, value)
|
165
|
+
|
166
|
+
def peek_with_priority(self) -> Tuple[float, Any]:
|
167
|
+
"""
|
168
|
+
Peek at the highest priority item with its priority.
|
169
|
+
|
170
|
+
Returns:
|
171
|
+
Tuple of (priority, value)
|
172
|
+
|
173
|
+
Raises:
|
174
|
+
IndexError: If heap is empty
|
175
|
+
"""
|
176
|
+
if self.is_empty():
|
177
|
+
raise IndexError("peek from empty priority queue")
|
178
|
+
|
179
|
+
priority, counter, value = self._heap[0]
|
180
|
+
actual_priority = -priority if self._is_max_heap else priority
|
181
|
+
return (actual_priority, value)
|
182
|
+
|
183
|
+
def pop_with_priority(self) -> Tuple[float, Any]:
|
184
|
+
"""
|
185
|
+
Extract and return the highest priority item with its priority.
|
186
|
+
|
187
|
+
Returns:
|
188
|
+
Tuple of (priority, value)
|
189
|
+
|
190
|
+
Raises:
|
191
|
+
IndexError: If heap is empty
|
192
|
+
"""
|
193
|
+
if self.is_empty():
|
194
|
+
raise IndexError("pop from empty priority queue")
|
195
|
+
|
196
|
+
priority, counter, value = heapq.heappop(self._heap)
|
197
|
+
actual_priority = -priority if self._is_max_heap else priority
|
198
|
+
return (actual_priority, value)
|
199
|
+
|
200
|
+
def pushpop(self, value: Any, priority: float = 0.0) -> Any:
|
201
|
+
"""
|
202
|
+
Push item then pop highest priority item (more efficient than separate ops).
|
203
|
+
|
204
|
+
Time: O(log n)
|
205
|
+
Space: O(1)
|
206
|
+
|
207
|
+
Returns:
|
208
|
+
The highest priority value after insertion
|
209
|
+
"""
|
210
|
+
actual_priority = -priority if self._is_max_heap else priority
|
211
|
+
priority_out, counter_out, value_out = heapq.heappushpop(
|
212
|
+
self._heap,
|
213
|
+
(actual_priority, self._counter, value)
|
214
|
+
)
|
215
|
+
self._counter += 1
|
216
|
+
return value_out
|
217
|
+
|
218
|
+
def replace(self, value: Any, priority: float = 0.0) -> Any:
|
219
|
+
"""
|
220
|
+
Pop highest priority item then push new item (more efficient than separate ops).
|
221
|
+
|
222
|
+
Time: O(log n)
|
223
|
+
Space: O(1)
|
224
|
+
|
225
|
+
Returns:
|
226
|
+
The popped value
|
227
|
+
|
228
|
+
Raises:
|
229
|
+
IndexError: If heap is empty
|
230
|
+
"""
|
231
|
+
if self.is_empty():
|
232
|
+
raise IndexError("replace on empty priority queue")
|
233
|
+
|
234
|
+
actual_priority = -priority if self._is_max_heap else priority
|
235
|
+
priority_out, counter_out, value_out = heapq.heapreplace(
|
236
|
+
self._heap,
|
237
|
+
(actual_priority, self._counter, value)
|
238
|
+
)
|
239
|
+
self._counter += 1
|
240
|
+
return value_out
|
241
|
+
|
242
|
+
# ============================================================================
|
243
|
+
# REQUIRED ABSTRACT METHODS (from ANodeStrategy)
|
244
|
+
# ============================================================================
|
245
|
+
|
246
|
+
def put(self, key: Any, value: Any = None) -> None:
|
247
|
+
"""Store value (uses key as priority if numeric, otherwise default priority)."""
|
248
|
+
try:
|
249
|
+
priority = float(key)
|
250
|
+
self.push(value if value is not None else key, priority)
|
251
|
+
except (ValueError, TypeError):
|
252
|
+
self.push(value if value is not None else key, 0.0)
|
253
|
+
|
254
|
+
def get(self, key: Any, default: Any = None) -> Any:
|
255
|
+
"""Get value in heap (O(n) - not efficient for heaps)."""
|
256
|
+
for _, _, val in self._heap:
|
257
|
+
if val == key:
|
258
|
+
return val
|
259
|
+
return default
|
260
|
+
|
261
|
+
def has(self, key: Any) -> bool:
|
262
|
+
"""Check if value exists (O(n))."""
|
263
|
+
for _, _, val in self._heap:
|
264
|
+
if val == key:
|
265
|
+
return True
|
266
|
+
return False
|
267
|
+
|
268
|
+
def delete(self, key: Any) -> bool:
|
269
|
+
"""Delete value from heap (O(n) - requires re-heapify)."""
|
270
|
+
for i, (priority, counter, val) in enumerate(self._heap):
|
271
|
+
if val == key:
|
55
272
|
self._heap.pop(i)
|
56
|
-
|
273
|
+
if self._heap:
|
274
|
+
heapq.heapify(self._heap)
|
57
275
|
return True
|
58
276
|
return False
|
59
277
|
|
278
|
+
def keys(self) -> Iterator[Any]:
|
279
|
+
"""Get all values as keys."""
|
280
|
+
for _, _, val in self._heap:
|
281
|
+
yield val
|
282
|
+
|
283
|
+
def values(self) -> Iterator[Any]:
|
284
|
+
"""Get all values."""
|
285
|
+
for _, _, val in self._heap:
|
286
|
+
yield val
|
287
|
+
|
288
|
+
def items(self) -> Iterator[tuple[Any, Any]]:
|
289
|
+
"""Get all items as (value, value) pairs."""
|
290
|
+
for _, _, val in self._heap:
|
291
|
+
yield (val, val)
|
292
|
+
|
293
|
+
# ============================================================================
|
294
|
+
# UTILITY METHODS
|
295
|
+
# ============================================================================
|
296
|
+
|
60
297
|
def size(self) -> int:
|
61
298
|
"""Get the number of items in the priority queue."""
|
62
299
|
return len(self._heap)
|
@@ -65,150 +302,325 @@ orithms like Dijkstra's.
|
|
65
302
|
"""Check if the priority queue is empty."""
|
66
303
|
return len(self._heap) == 0
|
67
304
|
|
305
|
+
def is_full(self) -> bool:
|
306
|
+
"""Check if heap has reached max_size."""
|
307
|
+
return self._max_size is not None and len(self._heap) >= self._max_size
|
308
|
+
|
309
|
+
def clear(self) -> None:
|
310
|
+
"""Clear all items from the priority queue."""
|
311
|
+
self._heap.clear()
|
312
|
+
self._counter = 0
|
313
|
+
self._record_access("clear")
|
314
|
+
|
315
|
+
def to_list(self) -> List[Tuple[float, Any]]:
|
316
|
+
"""Convert to sorted list of (priority, value) tuples."""
|
317
|
+
return sorted(
|
318
|
+
[(p if not self._is_max_heap else -p, v) for p, c, v in self._heap],
|
319
|
+
key=lambda x: x[0]
|
320
|
+
)
|
321
|
+
|
68
322
|
def to_native(self) -> Dict[str, Any]:
|
69
323
|
"""Convert priority queue to native dictionary format."""
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
324
|
+
return {
|
325
|
+
'items': [(p if not self._is_max_heap else -p, v) for p, c, v in self._heap],
|
326
|
+
'is_max_heap': self._is_max_heap
|
327
|
+
}
|
74
328
|
|
75
329
|
def from_native(self, data: Dict[str, Any]) -> None:
|
76
330
|
"""Load priority queue from native dictionary format."""
|
77
331
|
self._heap.clear()
|
78
|
-
|
79
|
-
|
332
|
+
self._counter = 0
|
333
|
+
self._is_max_heap = data.get('is_max_heap', False)
|
334
|
+
|
335
|
+
for priority, value in data.get('items', []):
|
336
|
+
self.push(value, priority)
|
80
337
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
338
|
+
# ============================================================================
|
339
|
+
# REQUIRED ABSTRACT METHODS (Linear Strategy Base)
|
340
|
+
# ============================================================================
|
341
|
+
|
342
|
+
def get_at_index(self, index: int) -> Any:
|
343
|
+
"""Get item at index in heap (order not guaranteed)."""
|
344
|
+
if 0 <= index < len(self._heap):
|
345
|
+
return self._heap[index][2]
|
346
|
+
raise IndexError(f"priority queue index out of range: {index}")
|
347
|
+
|
348
|
+
def set_at_index(self, index: int, value: Any) -> None:
|
349
|
+
"""Set item at index (not recommended - breaks heap property)."""
|
350
|
+
if 0 <= index < len(self._heap):
|
351
|
+
priority, counter, _ = self._heap[index]
|
352
|
+
self._heap[index] = (priority, counter, value)
|
353
|
+
else:
|
354
|
+
raise IndexError(f"priority queue index out of range: {index}")
|
355
|
+
|
356
|
+
def push_front(self, value: Any) -> None:
|
357
|
+
"""Push with highest priority."""
|
358
|
+
self.push(value, float('-inf') if not self._is_max_heap else float('inf'))
|
85
359
|
|
86
|
-
def
|
87
|
-
"""
|
360
|
+
def push_back(self, value: Any) -> None:
|
361
|
+
"""Push with lowest priority."""
|
362
|
+
self.push(value, float('inf') if not self._is_max_heap else float('-inf'))
|
363
|
+
|
364
|
+
def pop_front(self) -> Any:
|
365
|
+
"""Pop highest priority item (standard pop)."""
|
366
|
+
return self.pop()
|
367
|
+
|
368
|
+
def pop_back(self) -> Any:
|
369
|
+
"""Pop lowest priority item (O(n) - not efficient)."""
|
88
370
|
if self.is_empty():
|
89
|
-
|
371
|
+
raise IndexError("pop from empty priority queue")
|
90
372
|
|
91
|
-
|
92
|
-
|
373
|
+
# Find item with worst priority
|
374
|
+
worst_idx = max(range(len(self._heap)), key=lambda i: self._heap[i][0])
|
375
|
+
value = self._heap[worst_idx][2]
|
376
|
+
self._heap.pop(worst_idx)
|
377
|
+
if self._heap: # Re-heapify if not empty
|
378
|
+
heapq.heapify(self._heap)
|
379
|
+
return value
|
93
380
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
381
|
+
# Behavioral views
|
382
|
+
def as_linked_list(self):
|
383
|
+
"""Priority queue can be viewed as ordered linked list."""
|
384
|
+
return self
|
385
|
+
|
386
|
+
def as_stack(self):
|
387
|
+
"""Priority queue cannot behave as Stack."""
|
388
|
+
raise NotImplementedError("PriorityQueue cannot behave as Stack - use StackStrategy instead")
|
389
|
+
|
390
|
+
def as_queue(self):
|
391
|
+
"""Priority queue cannot behave as standard Queue."""
|
392
|
+
raise NotImplementedError("PriorityQueue cannot behave as Queue - use QueueStrategy instead")
|
393
|
+
|
394
|
+
def as_deque(self):
|
395
|
+
"""Priority queue cannot behave as Deque."""
|
396
|
+
raise NotImplementedError("PriorityQueue cannot behave as Deque - use DequeStrategy instead")
|
397
|
+
|
398
|
+
# ============================================================================
|
399
|
+
# PYTHON SPECIAL METHODS
|
400
|
+
# ============================================================================
|
401
|
+
|
402
|
+
def __len__(self) -> int:
|
403
|
+
"""Return the number of items in the priority queue."""
|
404
|
+
return len(self._heap)
|
405
|
+
|
406
|
+
def __bool__(self) -> bool:
|
407
|
+
"""Return True if priority queue is not empty."""
|
408
|
+
return bool(self._heap)
|
409
|
+
|
410
|
+
def __iter__(self) -> Iterator[Any]:
|
411
|
+
"""Iterate through items (order not guaranteed - heap order)."""
|
412
|
+
for _, _, value in self._heap:
|
413
|
+
yield value
|
414
|
+
|
415
|
+
def __repr__(self) -> str:
|
416
|
+
"""Professional string representation."""
|
417
|
+
heap_type = "max-heap" if self._is_max_heap else "min-heap"
|
418
|
+
top = self.peek() if not self.is_empty() else None
|
419
|
+
return f"PriorityQueueStrategy(size={len(self._heap)}, type={heap_type}, top={top})"
|
420
|
+
|
421
|
+
def __str__(self) -> str:
|
422
|
+
"""Human-readable string representation."""
|
423
|
+
heap_type = "MaxHeap" if self._is_max_heap else "MinHeap"
|
424
|
+
return f"{heap_type}[size={len(self._heap)}]"
|
425
|
+
|
426
|
+
# ============================================================================
|
427
|
+
# ADVANCED HEAP OPERATIONS
|
428
|
+
# ============================================================================
|
429
|
+
|
430
|
+
def nsmallest(self, n: int) -> List[Tuple[float, Any]]:
|
431
|
+
"""
|
432
|
+
Get n smallest priority items without removing them.
|
98
433
|
|
99
|
-
|
100
|
-
max_heap = [(-priority, counter, key, value) for priority, counter, key, value in self._heap]
|
101
|
-
heapq.heapify(max_heap)
|
434
|
+
Time: O(n log k) where k = min(n, heap_size)
|
102
435
|
|
103
|
-
|
104
|
-
|
436
|
+
Returns:
|
437
|
+
List of (priority, value) tuples
|
438
|
+
"""
|
439
|
+
items = heapq.nsmallest(n, self._heap, key=lambda x: x[0])
|
440
|
+
return [(p if not self._is_max_heap else -p, v) for p, c, v in items]
|
441
|
+
|
442
|
+
def nlargest(self, n: int) -> List[Tuple[float, Any]]:
|
443
|
+
"""
|
444
|
+
Get n largest priority items without removing them.
|
105
445
|
|
106
|
-
|
107
|
-
for i, (p, c, k, v) in enumerate(self._heap):
|
108
|
-
if k == key and c == counter:
|
109
|
-
self._heap.pop(i)
|
110
|
-
break
|
446
|
+
Time: O(n log k) where k = min(n, heap_size)
|
111
447
|
|
112
|
-
|
448
|
+
Returns:
|
449
|
+
List of (priority, value) tuples
|
450
|
+
"""
|
451
|
+
items = heapq.nlargest(n, self._heap, key=lambda x: x[0])
|
452
|
+
return [(p if not self._is_max_heap else -p, v) for p, c, v in items]
|
113
453
|
|
114
|
-
def
|
115
|
-
"""
|
116
|
-
|
117
|
-
return None
|
454
|
+
def merge(self, other: 'PriorityQueueStrategy') -> 'PriorityQueueStrategy':
|
455
|
+
"""
|
456
|
+
Merge two priority queues.
|
118
457
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
"""
|
124
|
-
|
125
|
-
return None
|
458
|
+
Time: O((n + m) log(n + m))
|
459
|
+
|
460
|
+
Returns:
|
461
|
+
New merged priority queue
|
462
|
+
"""
|
463
|
+
merged = PriorityQueueStrategy(is_max_heap=self._is_max_heap)
|
126
464
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
max_item = (key, value, priority)
|
465
|
+
# Merge heaps efficiently
|
466
|
+
merged._heap = list(heapq.merge(self._heap, other._heap, key=lambda x: x[0]))
|
467
|
+
merged._counter = self._counter + other._counter
|
131
468
|
|
132
|
-
return
|
469
|
+
return merged
|
133
470
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
return
|
471
|
+
# ============================================================================
|
472
|
+
# COMPATIBILITY INTERFACE
|
473
|
+
# ============================================================================
|
474
|
+
|
475
|
+
def to_list(self) -> List[Tuple[float, Any]]:
|
476
|
+
"""Convert to sorted list of (priority, value) tuples."""
|
477
|
+
sorted_items = sorted(self._heap, key=lambda x: x[0])
|
478
|
+
return [(p if not self._is_max_heap else -p, v) for p, c, v in sorted_items]
|
479
|
+
|
480
|
+
def to_native(self) -> Dict[str, Any]:
|
481
|
+
"""Convert priority queue to native dictionary format."""
|
482
|
+
return {
|
483
|
+
'items': [(p if not self._is_max_heap else -p, v) for p, c, v in self._heap],
|
484
|
+
'is_max_heap': self._is_max_heap,
|
485
|
+
'size': len(self._heap)
|
486
|
+
}
|
142
487
|
|
143
|
-
def
|
144
|
-
"""
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
488
|
+
def from_native(self, data: Dict[str, Any]) -> None:
|
489
|
+
"""Load priority queue from native dictionary format."""
|
490
|
+
self._heap.clear()
|
491
|
+
self._counter = 0
|
492
|
+
self._is_max_heap = data.get('is_max_heap', False)
|
493
|
+
|
494
|
+
for priority, value in data.get('items', []):
|
495
|
+
self.push(value, priority)
|
496
|
+
|
497
|
+
# ============================================================================
|
498
|
+
# UTILITY METHODS
|
499
|
+
# ============================================================================
|
500
|
+
|
501
|
+
def size(self) -> int:
|
502
|
+
"""Get the number of items in the priority queue."""
|
503
|
+
return len(self._heap)
|
504
|
+
|
505
|
+
def is_empty(self) -> bool:
|
506
|
+
"""Check if the priority queue is empty."""
|
507
|
+
return len(self._heap) == 0
|
508
|
+
|
509
|
+
def is_full(self) -> bool:
|
510
|
+
"""Check if heap has reached max_size."""
|
511
|
+
return self._max_size is not None and len(self._heap) >= self._max_size
|
149
512
|
|
150
513
|
def clear(self) -> None:
|
151
514
|
"""Clear all items from the priority queue."""
|
152
515
|
self._heap.clear()
|
153
516
|
self._counter = 0
|
517
|
+
self._record_access("clear")
|
154
518
|
|
155
|
-
|
156
|
-
|
519
|
+
# ============================================================================
|
520
|
+
# REQUIRED ABSTRACT METHODS (Linear Strategy Base)
|
521
|
+
# ============================================================================
|
522
|
+
|
523
|
+
def get_at_index(self, index: int) -> Any:
|
524
|
+
"""Get item at index (heap order, not priority order)."""
|
525
|
+
if 0 <= index < len(self._heap):
|
526
|
+
return self._heap[index][2]
|
527
|
+
raise IndexError(f"priority queue index out of range: {index}")
|
528
|
+
|
529
|
+
def set_at_index(self, index: int, value: Any) -> None:
|
530
|
+
"""Set item at index (breaks heap property - requires re-heapify)."""
|
157
531
|
if 0 <= index < len(self._heap):
|
158
|
-
priority, counter,
|
159
|
-
|
160
|
-
|
532
|
+
priority, counter, _ = self._heap[index]
|
533
|
+
self._heap[index] = (priority, counter, value)
|
534
|
+
else:
|
535
|
+
raise IndexError(f"priority queue index out of range: {index}")
|
161
536
|
|
162
537
|
def push_front(self, value: Any) -> None:
|
163
|
-
"""Push
|
164
|
-
|
165
|
-
self.insert_with_priority(key, value, float('inf'))
|
538
|
+
"""Push with highest priority."""
|
539
|
+
self.push(value, float('-inf') if not self._is_max_heap else float('inf'))
|
166
540
|
|
167
541
|
def push_back(self, value: Any) -> None:
|
168
|
-
"""Push
|
169
|
-
|
170
|
-
self.insert_with_priority(key, value, float('-inf'))
|
542
|
+
"""Push with lowest priority."""
|
543
|
+
self.push(value, float('inf') if not self._is_max_heap else float('-inf'))
|
171
544
|
|
172
|
-
def __iter__(self) -> Iterator[Any]:
|
173
|
-
"""Iterate through items (order not guaranteed)."""
|
174
|
-
for priority, counter, key, value in self._heap:
|
175
|
-
yield value
|
176
|
-
|
177
|
-
def __repr__(self) -> str:
|
178
|
-
"""String representation of the priority queue."""
|
179
|
-
min_item = self.peek_min()
|
180
|
-
max_item = self.peek_max()
|
181
|
-
return f"PriorityQueueStrategy(size={len(self._heap)}, min={min_item[2] if min_item else None}, max={max_item[2] if max_item else None})"
|
182
|
-
|
183
|
-
# Required abstract methods from base classes
|
184
545
|
def pop_front(self) -> Any:
|
185
|
-
"""
|
186
|
-
|
187
|
-
return result[1] if result else None
|
546
|
+
"""Pop highest priority item."""
|
547
|
+
return self.pop()
|
188
548
|
|
189
549
|
def pop_back(self) -> Any:
|
190
|
-
"""
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
self._heap
|
550
|
+
"""Pop lowest priority item (inefficient O(n))."""
|
551
|
+
if self.is_empty():
|
552
|
+
raise IndexError("pop from empty priority queue")
|
553
|
+
|
554
|
+
worst_idx = max(range(len(self._heap)), key=lambda i: self._heap[i][0])
|
555
|
+
value = self._heap[worst_idx][2]
|
556
|
+
self._heap.pop(worst_idx)
|
557
|
+
if self._heap:
|
558
|
+
heapq.heapify(self._heap)
|
559
|
+
return value
|
199
560
|
|
561
|
+
# Behavioral views
|
200
562
|
def as_linked_list(self):
|
201
|
-
"""
|
563
|
+
"""Priority queue can be viewed as ordered linked list."""
|
202
564
|
return self
|
203
565
|
|
204
566
|
def as_stack(self):
|
205
|
-
"""
|
567
|
+
"""Priority queue cannot behave as Stack."""
|
206
568
|
raise NotImplementedError("PriorityQueue cannot behave as Stack")
|
207
569
|
|
208
570
|
def as_queue(self):
|
209
|
-
"""
|
571
|
+
"""Priority queue cannot behave as Queue."""
|
210
572
|
raise NotImplementedError("PriorityQueue cannot behave as Queue")
|
211
573
|
|
212
574
|
def as_deque(self):
|
213
|
-
"""
|
575
|
+
"""Priority queue cannot behave as Deque."""
|
214
576
|
raise NotImplementedError("PriorityQueue cannot behave as Deque")
|
577
|
+
|
578
|
+
# ============================================================================
|
579
|
+
# PYTHON SPECIAL METHODS
|
580
|
+
# ============================================================================
|
581
|
+
|
582
|
+
def __iter__(self) -> Iterator[Any]:
|
583
|
+
"""Iterate in heap order (not priority order)."""
|
584
|
+
for _, _, value in self._heap:
|
585
|
+
yield value
|
586
|
+
|
587
|
+
def __repr__(self) -> str:
|
588
|
+
"""Professional string representation."""
|
589
|
+
heap_type = "max-heap" if self._is_max_heap else "min-heap"
|
590
|
+
return f"PriorityQueueStrategy(size={len(self._heap)}, type={heap_type})"
|
591
|
+
|
592
|
+
# ============================================================================
|
593
|
+
# PERFORMANCE METADATA
|
594
|
+
# ============================================================================
|
595
|
+
|
596
|
+
@property
|
597
|
+
def backend_info(self) -> Dict[str, Any]:
|
598
|
+
"""Get backend implementation info."""
|
599
|
+
return {
|
600
|
+
'strategy': 'PRIORITY_QUEUE',
|
601
|
+
'backend': 'heapq (binary heap)',
|
602
|
+
'heap_type': 'max-heap' if self._is_max_heap else 'min-heap',
|
603
|
+
'complexity': {
|
604
|
+
'push': 'O(log n)',
|
605
|
+
'pop': 'O(log n)',
|
606
|
+
'peek': 'O(1)',
|
607
|
+
'pushpop': 'O(log n)',
|
608
|
+
'replace': 'O(log n)',
|
609
|
+
'space': 'O(n)'
|
610
|
+
},
|
611
|
+
'thread_safe': False,
|
612
|
+
'max_size': self._max_size if self._max_size else 'unlimited'
|
613
|
+
}
|
614
|
+
|
615
|
+
@property
|
616
|
+
def metrics(self) -> Dict[str, Any]:
|
617
|
+
"""Get performance metrics."""
|
618
|
+
return {
|
619
|
+
'size': len(self._heap),
|
620
|
+
'is_empty': self.is_empty(),
|
621
|
+
'is_full': self.is_full(),
|
622
|
+
'max_size': self._max_size,
|
623
|
+
'is_max_heap': self._is_max_heap,
|
624
|
+
'counter': self._counter,
|
625
|
+
'memory_usage': f"{len(self._heap) * 24} bytes (estimated)"
|
626
|
+
}
|