exonware-xwnode 0.0.1.22__py3-none-any.whl → 0.0.1.24__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 +1 -1
- exonware/xwnode/__init__.py +18 -5
- exonware/xwnode/add_strategy_types.py +165 -0
- 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 +2 -2
- exonware/xwnode/common/management/migration.py +3 -3
- exonware/xwnode/common/monitoring/__init__.py +3 -5
- exonware/xwnode/common/monitoring/metrics.py +6 -2
- exonware/xwnode/common/monitoring/pattern_detector.py +1 -1
- exonware/xwnode/common/monitoring/performance_monitor.py +5 -1
- exonware/xwnode/common/patterns/__init__.py +3 -5
- exonware/xwnode/common/patterns/flyweight.py +5 -1
- exonware/xwnode/common/patterns/registry.py +202 -183
- 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.24.dist-info/METADATA +900 -0
- exonware_xwnode-0.0.1.24.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.22.dist-info/METADATA +0 -168
- exonware_xwnode-0.0.1.22.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.22.dist-info → exonware_xwnode-0.0.1.24.dist-info}/WHEEL +0 -0
- {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.24.dist-info}/licenses/LICENSE +0 -0
@@ -57,15 +57,80 @@ class RedBlackTreeNode:
|
|
57
57
|
|
58
58
|
class RedBlackTreeStrategy(ANodeTreeStrategy):
|
59
59
|
"""
|
60
|
-
Red-
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
Red-Black Tree strategy for self-balancing binary search trees.
|
61
|
+
|
62
|
+
WHY Red-Black Tree:
|
63
|
+
- Guaranteed O(log n) worst-case for insert, search, delete
|
64
|
+
- Simpler than AVL trees (less strict balancing = fewer rotations)
|
65
|
+
- Industry standard (used in Java TreeMap, C++ std::map, Linux kernel)
|
66
|
+
- Better insert/delete performance than AVL (relaxed balancing)
|
67
|
+
- Maintains sorted order with efficient range queries
|
68
|
+
|
69
|
+
WHY this implementation:
|
70
|
+
- Color-based balancing rules (simpler than height-based AVL)
|
71
|
+
- Parent pointers enable bottom-up fixup after operations
|
72
|
+
- Case-based rotation logic handles all red-black violations
|
73
|
+
- Tracks rotations and statistics for performance monitoring
|
74
|
+
- Preserves BST property while maintaining logarithmic height
|
75
|
+
|
76
|
+
Time Complexity:
|
77
|
+
- Insert: O(log n) guaranteed (at most 2 rotations)
|
78
|
+
- Search: O(log n) guaranteed
|
79
|
+
- Delete: O(log n) guaranteed (at most 3 rotations)
|
80
|
+
- Min/Max: O(log n) - leftmost/rightmost traversal
|
81
|
+
- Iteration: O(n) in sorted order
|
82
|
+
|
83
|
+
Space Complexity: O(n) - one node per key + parent pointers + color bit
|
84
|
+
|
85
|
+
Trade-offs:
|
86
|
+
- Advantage: Fewer rotations than AVL (better insert/delete performance)
|
87
|
+
- Advantage: Guaranteed O(log n) worst-case (unlike Skip List)
|
88
|
+
- Limitation: Slightly taller than AVL trees (height ≤ 2*log(n+1))
|
89
|
+
- Limitation: More complex than simple BST (color rules and rotations)
|
90
|
+
- Compared to AVL: Faster inserts/deletes, slightly slower searches
|
91
|
+
- Compared to B-Tree: Better for in-memory, worse for disk-based storage
|
92
|
+
|
93
|
+
Best for:
|
94
|
+
- General-purpose sorted collections (maps, sets)
|
95
|
+
- When insert/delete and search performance matter equally
|
96
|
+
- Implementing associative containers (key-value stores)
|
97
|
+
- When guaranteed O(log n) worst-case is required
|
98
|
+
- In-memory databases and indices
|
99
|
+
|
100
|
+
Not recommended for:
|
101
|
+
- Read-heavy workloads (AVL Tree is better)
|
102
|
+
- Disk-based storage (B-Tree is better)
|
103
|
+
- Simple, unsorted data (Hash Map is faster)
|
104
|
+
- Memory-constrained environments (overhead for parent pointers + color)
|
105
|
+
- When probabilistic guarantees suffice (Skip List is simpler)
|
106
|
+
|
107
|
+
Following eXonware Priorities:
|
108
|
+
1. Usability: Self-balancing ensures consistent O(log n) performance
|
109
|
+
2. Maintainability: Industry-standard algorithm, well-documented
|
110
|
+
3. Performance: Optimized balance between insert and search operations
|
111
|
+
4. Extensibility: Can be enhanced with augmentation (order statistics, intervals)
|
112
|
+
5. Security: Input validation, bounded height prevents worst-case attacks
|
113
|
+
|
114
|
+
Industry Best Practices:
|
115
|
+
- Follows Cormen CLRS textbook implementation
|
116
|
+
- Maintains 5 red-black properties:
|
117
|
+
1. Every node is red or black
|
118
|
+
2. Root is black
|
119
|
+
3. Leaves (NIL) are black
|
120
|
+
4. Red nodes have black children
|
121
|
+
5. All paths have same number of black nodes
|
122
|
+
- Uses case-based fixup (standard approach)
|
123
|
+
- Tracks performance statistics
|
124
|
+
|
125
|
+
Performance Note:
|
126
|
+
Red-Black Trees provide GUARANTEED O(log n) in worst-case.
|
127
|
+
Height is at most 2*log(n+1), ensuring consistent performance
|
128
|
+
even with adversarial input patterns. This makes them ideal for
|
129
|
+
production systems requiring predictable latency.
|
130
|
+
"""
|
64
131
|
|
65
132
|
# Strategy type classification
|
66
133
|
STRATEGY_TYPE = NodeType.TREE
|
67
|
-
ing rules and rotations.
|
68
|
-
"""
|
69
134
|
|
70
135
|
def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
|
71
136
|
"""Initialize the red-black tree strategy."""
|
@@ -267,98 +332,136 @@ ing rules and rotations.
|
|
267
332
|
if not node:
|
268
333
|
return False
|
269
334
|
|
270
|
-
#
|
335
|
+
# Store original color
|
336
|
+
original_color = node.color
|
337
|
+
|
338
|
+
# Case 1: No left child
|
271
339
|
if not node.left:
|
272
340
|
replacement = node.right
|
341
|
+
self._transplant(node, node.right)
|
342
|
+
# Case 2: No right child
|
273
343
|
elif not node.right:
|
274
344
|
replacement = node.left
|
345
|
+
self._transplant(node, node.left)
|
346
|
+
# Case 3: Two children
|
275
347
|
else:
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
348
|
+
# Find successor (minimum in right subtree)
|
349
|
+
successor = self._find_min(node.right)
|
350
|
+
original_color = successor.color
|
351
|
+
replacement = successor.right
|
352
|
+
|
353
|
+
if successor.parent == node:
|
354
|
+
# Successor is direct right child
|
355
|
+
if replacement:
|
356
|
+
replacement.parent = successor
|
357
|
+
else:
|
358
|
+
# Successor is deeper in tree
|
359
|
+
self._transplant(successor, successor.right)
|
360
|
+
successor.right = node.right
|
361
|
+
successor.right.parent = successor
|
362
|
+
|
363
|
+
# Replace node with successor
|
364
|
+
self._transplant(node, successor)
|
365
|
+
successor.left = node.left
|
366
|
+
successor.left.parent = successor
|
367
|
+
successor.color = node.color
|
291
368
|
|
292
369
|
# Fix red-black tree properties if needed
|
293
|
-
if
|
370
|
+
if original_color == 'BLACK' and replacement:
|
294
371
|
self._fix_deletion(replacement)
|
295
|
-
elif node.is_black():
|
296
|
-
self._fix_deletion(None)
|
297
372
|
|
298
373
|
self._size -= 1
|
299
374
|
self._total_deletions += 1
|
300
375
|
return True
|
301
376
|
|
302
|
-
def
|
377
|
+
def _transplant(self, old_node: RedBlackTreeNode, new_node: Optional[RedBlackTreeNode]) -> None:
|
378
|
+
"""Replace old_node with new_node in the tree."""
|
379
|
+
if not old_node.parent:
|
380
|
+
self._root = new_node
|
381
|
+
elif old_node == old_node.parent.left:
|
382
|
+
old_node.parent.left = new_node
|
383
|
+
else:
|
384
|
+
old_node.parent.right = new_node
|
385
|
+
|
386
|
+
if new_node:
|
387
|
+
new_node.parent = old_node.parent
|
388
|
+
|
389
|
+
def _fix_deletion(self, node: RedBlackTreeNode) -> None:
|
303
390
|
"""Fix red-black tree properties after deletion."""
|
304
|
-
while node != self._root and
|
305
|
-
|
306
|
-
|
391
|
+
while node != self._root and node.is_black():
|
392
|
+
parent = node.parent
|
393
|
+
if not parent:
|
394
|
+
break
|
395
|
+
|
396
|
+
if node == parent.left:
|
397
|
+
sibling = parent.right
|
307
398
|
if sibling and sibling.is_red():
|
308
399
|
# Case 1: Sibling is red
|
309
400
|
sibling.set_black()
|
310
|
-
|
311
|
-
self._rotate_left(
|
312
|
-
sibling =
|
401
|
+
parent.set_red()
|
402
|
+
self._rotate_left(parent)
|
403
|
+
sibling = parent.right
|
313
404
|
|
314
|
-
if
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
node = node.parent
|
319
|
-
else:
|
320
|
-
if not sibling.right or sibling.right.is_black():
|
321
|
-
# Case 3: Sibling's right child is black
|
322
|
-
sibling.left.set_black()
|
405
|
+
if sibling:
|
406
|
+
if ((not sibling.left or sibling.left.is_black()) and
|
407
|
+
(not sibling.right or sibling.right.is_black())):
|
408
|
+
# Case 2: Sibling and its children are black
|
323
409
|
sibling.set_red()
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
410
|
+
node = parent
|
411
|
+
else:
|
412
|
+
if not sibling.right or sibling.right.is_black():
|
413
|
+
# Case 3: Sibling's right child is black
|
414
|
+
if sibling.left:
|
415
|
+
sibling.left.set_black()
|
416
|
+
sibling.set_red()
|
417
|
+
self._rotate_right(sibling)
|
418
|
+
sibling = parent.right
|
419
|
+
|
420
|
+
# Case 4: Sibling's right child is red
|
421
|
+
if sibling:
|
422
|
+
sibling.color = parent.color
|
423
|
+
parent.set_black()
|
424
|
+
if sibling.right:
|
425
|
+
sibling.right.set_black()
|
426
|
+
self._rotate_left(parent)
|
427
|
+
node = self._root
|
428
|
+
else:
|
429
|
+
break
|
333
430
|
else:
|
334
431
|
# Mirror cases for right side
|
335
|
-
sibling =
|
432
|
+
sibling = parent.left
|
336
433
|
if sibling and sibling.is_red():
|
337
434
|
# Case 1: Sibling is red
|
338
435
|
sibling.set_black()
|
339
|
-
|
340
|
-
self._rotate_right(
|
341
|
-
sibling =
|
436
|
+
parent.set_red()
|
437
|
+
self._rotate_right(parent)
|
438
|
+
sibling = parent.left
|
342
439
|
|
343
|
-
if
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
node = node.parent
|
348
|
-
else:
|
349
|
-
if not sibling.left or sibling.left.is_black():
|
350
|
-
# Case 3: Sibling's left child is black
|
351
|
-
sibling.right.set_black()
|
440
|
+
if sibling:
|
441
|
+
if ((not sibling.right or sibling.right.is_black()) and
|
442
|
+
(not sibling.left or sibling.left.is_black())):
|
443
|
+
# Case 2: Sibling and its children are black
|
352
444
|
sibling.set_red()
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
445
|
+
node = parent
|
446
|
+
else:
|
447
|
+
if not sibling.left or sibling.left.is_black():
|
448
|
+
# Case 3: Sibling's left child is black
|
449
|
+
if sibling.right:
|
450
|
+
sibling.right.set_black()
|
451
|
+
sibling.set_red()
|
452
|
+
self._rotate_left(sibling)
|
453
|
+
sibling = parent.left
|
454
|
+
|
455
|
+
# Case 4: Sibling's left child is red
|
456
|
+
if sibling:
|
457
|
+
sibling.color = parent.color
|
458
|
+
parent.set_black()
|
459
|
+
if sibling.left:
|
460
|
+
sibling.left.set_black()
|
461
|
+
self._rotate_right(parent)
|
462
|
+
node = self._root
|
463
|
+
else:
|
464
|
+
break
|
362
465
|
|
363
466
|
if node:
|
364
467
|
node.set_black()
|
@@ -412,6 +515,14 @@ ing rules and rotations.
|
|
412
515
|
"""Get number of key-value pairs."""
|
413
516
|
return self._size
|
414
517
|
|
518
|
+
def __len__(self) -> int:
|
519
|
+
"""Get number of key-value pairs."""
|
520
|
+
return self._size
|
521
|
+
|
522
|
+
def to_native(self) -> Dict[str, Any]:
|
523
|
+
"""Convert to native Python dict."""
|
524
|
+
return dict(self.items())
|
525
|
+
|
415
526
|
def is_empty(self) -> bool:
|
416
527
|
"""Check if tree is empty."""
|
417
528
|
return self._root is None
|
@@ -1,8 +1,21 @@
|
|
1
1
|
"""
|
2
|
+
#exonware/xwnode/src/exonware/xwnode/nodes/strategies/roaring_bitmap.py
|
3
|
+
|
2
4
|
Roaring Bitmap Node Strategy Implementation
|
3
5
|
|
6
|
+
Status: Production Ready ✅
|
7
|
+
True Purpose: Highly compressed bitmap operations for sparse data
|
8
|
+
Complexity: O(log n) arrays, O(1) bitmaps - hybrid approach
|
9
|
+
Production Features: ✓ Hybrid Containers, ✓ Auto-conversion, ✓ Set Operations, ✓ Compression
|
10
|
+
|
4
11
|
This module implements the ROARING_BITMAP strategy for highly compressed
|
5
12
|
bitmap operations with excellent performance for sparse data.
|
13
|
+
|
14
|
+
Company: eXonware.com
|
15
|
+
Author: Eng. Muhammad AlShehri
|
16
|
+
Email: connect@exonware.com
|
17
|
+
Version: 0.0.1.24
|
18
|
+
Generation Date: October 12, 2025
|
6
19
|
"""
|
7
20
|
|
8
21
|
from typing import Any, Iterator, List, Dict, Optional, Set, Tuple
|
@@ -394,9 +407,9 @@ ormance characteristics.
|
|
394
407
|
removed_count += 1
|
395
408
|
return removed_count
|
396
409
|
|
397
|
-
def union(self, other: '
|
410
|
+
def union(self, other: 'RoaringBitmapStrategy') -> 'RoaringBitmapStrategy':
|
398
411
|
"""Union with another roaring bitmap."""
|
399
|
-
result =
|
412
|
+
result = RoaringBitmapStrategy(traits=self.traits)
|
400
413
|
|
401
414
|
# Union all containers
|
402
415
|
all_highs = set(self._containers.keys()) | set(other._containers.keys())
|
@@ -417,9 +430,9 @@ ormance characteristics.
|
|
417
430
|
|
418
431
|
return result
|
419
432
|
|
420
|
-
def intersection(self, other: '
|
433
|
+
def intersection(self, other: 'RoaringBitmapStrategy') -> 'RoaringBitmapStrategy':
|
421
434
|
"""Intersection with another roaring bitmap."""
|
422
|
-
result =
|
435
|
+
result = RoaringBitmapStrategy(traits=self.traits)
|
423
436
|
|
424
437
|
# Intersect only common containers
|
425
438
|
common_highs = set(self._containers.keys()) & set(other._containers.keys())
|
@@ -436,9 +449,9 @@ ormance characteristics.
|
|
436
449
|
|
437
450
|
return result
|
438
451
|
|
439
|
-
def difference(self, other: '
|
452
|
+
def difference(self, other: 'RoaringBitmapStrategy') -> 'RoaringBitmapStrategy':
|
440
453
|
"""Difference with another roaring bitmap."""
|
441
|
-
result =
|
454
|
+
result = RoaringBitmapStrategy(traits=self.traits)
|
442
455
|
|
443
456
|
for high, container in self._containers.items():
|
444
457
|
self_values = set(container.to_array())
|