stl_treemap.tree_multiset
Ordered multiset backed by a red-black tree (duplicate keys allowed).
1"""Ordered multiset backed by a red-black tree (duplicate keys allowed).""" 2 3from __future__ import annotations 4 5from collections.abc import Callable, Iterable 6from typing import Any 7 8from stl_treemap.insertion_result import InsertionResult 9from stl_treemap.iterators import ReverseIterator, TreeIterator 10from stl_treemap.policies import KeyOnlyPolicy 11from stl_treemap.py_iterators import PyIterator, PyReverseIterator 12from stl_treemap.tree import Tree 13from stl_treemap.tree_node import TreeNode 14 15 16class TreeMultiSet[K]: 17 """ 18 Ordered multiset of keys backed by a red-black tree. 19 20 Unlike TreeSet, multiple equal keys are allowed. Elements are kept in 21 ascending order. Lookup, insertion, and deletion are all O(log n). 22 23 Example:: 24 25 s = TreeMultiSet() 26 s.add(1) 27 s.add(2) 28 s.add(2) 29 for key in s: 30 print(key) # 1, 2, 2 31 """ 32 33 def __init__(self, iterable: Iterable[K] | None = None, *args) -> None: 34 """ 35 Create an empty multiset, or pre-populate it from an iterable of keys. 36 37 Duplicate keys are preserved (multiset semantics). 38 39 Args: 40 iterable: Optional iterable of keys. 41 args: initial keys could be provided as extra parameters 42 43 Raises: 44 TypeError: When *iterable* is not iterable. 45 46 Example:: 47 48 s = TreeMultiSet() 49 s = TreeMultiSet([1, 2, 2, 3]) # {1,2,2,3} 50 s = TreeMultiSet({1, 2}) # {1,2} 51 s = TreeMultiSet(None, 1, 2, 1, 2) # {1,1,2,2} 52 53 """ 54 self._t: Tree[K, K] = Tree() 55 self._t.value_policy = KeyOnlyPolicy() 56 if iterable is not None: 57 self.update(iterable) 58 if args: 59 self.update(args) 60 61 def update(self, *iterables: Iterable[K]) -> None: 62 """ 63 Add contents from all provided iterables to the current set. 64 65 Duplicate keys are preserved (multiset semantics). 66 67 Args: 68 iterables: One or more iterables containing keys. 69 70 Raises: 71 TypeError: When *iterable* is not iterable. 72 73 Example:: 74 75 s = TreeMultiSet() 76 s.update([1, 2, 2, 3]) # {1,2,2,3} 77 78 """ 79 for iterable in iterables: 80 if not hasattr(iterable, "__iter__"): 81 raise TypeError("TreeMultiSet accepts only iterable objects") 82 for k in iterable: 83 self.add(k) 84 85 # ------------------------------------------------------------------ 86 # Core mutation 87 # ------------------------------------------------------------------ 88 89 def clear(self) -> None: 90 """ 91 Remove all elements. 92 93 Example:: 94 95 s = TreeMultiSet([1, 2, 3]) 96 s.clear() 97 len(s) # 0 98 99 """ 100 self._t.clear() 101 102 def add(self, key: K) -> None: 103 """ 104 Insert *key*, always adding a new entry even if an equal key exists. 105 106 Example:: 107 108 s = TreeMultiSet() 109 s.add(1) 110 s.add(1) 111 len(s) # 2 112 113 """ 114 n: TreeNode[K, K] = TreeNode() 115 n.key = key 116 self._t.insert_multi(n) 117 118 def discard(self, key: K) -> None: 119 """ 120 Remove one occurrence of *key* if present; do nothing when absent. 121 122 Example:: 123 124 s = TreeMultiSet([1, 2, 2, 3]) 125 s.discard(2) # s is now {1,2,3} 126 s.discard(99) # no-op 127 128 """ 129 it = self._t.find(key) 130 if not it.equals(self._t.end()): 131 self._t.erase(it.node) 132 133 def remove(self, key: K) -> None: 134 """ 135 Remove one occurrence of *key*, raising KeyError when absent. 136 137 Args: 138 key: Key to remove. 139 140 Raises: 141 KeyError: When *key* is not present. 142 143 Example:: 144 145 s = TreeMultiSet([1, 2, 2, 3]) 146 s.remove(2) # s is now {1,2,3} 147 s.remove(99) # raises KeyError 148 149 """ 150 it = self._t.find(key) 151 if not it.equals(self._t.end()): 152 self._t.erase(it.node) 153 else: 154 raise KeyError(key) 155 156 def delete(self, key: K) -> None: 157 """ 158 @private Remove one occurrence of *key* if present; alias for discard(). 159 160 Example:: 161 162 s = TreeMultiSet([1, 2, 2, 3]) 163 s.delete(2) # s is now {1,2,3} 164 s.delete(99) # no-op 165 166 """ 167 self.discard(key) 168 169 def pop(self, key: K | None = None, default: K | None = None) -> K | None: 170 """ 171 Remove one occurrence of *key* and return it, or return *default* when absent. 172 173 When called with no arguments, removes and returns the smallest element. 174 175 Args: 176 key: Key to remove. When None, the smallest element is removed. 177 default: Value to return when *key* is absent. 178 179 Raises: 180 KeyError: When called with no arguments on an empty set. 181 182 Example:: 183 184 s = TreeMultiSet([1, 2, 2, 3]) 185 s.pop(2) # 2, s is now {1,2,3} 186 s.pop(9) # None 187 s.pop(9, 0) # 0 188 s.pop() # 1 — removes and returns smallest element 189 190 """ 191 if self.size == 0: 192 raise KeyError("pop from an empty set") 193 it = self._t.find(key) if key is not None else self.begin() 194 if not it.equals(self._t.end()): 195 k = it.key 196 self._t.erase(it.node) 197 return k 198 return default 199 200 # ------------------------------------------------------------------ 201 # Queries 202 # ------------------------------------------------------------------ 203 204 def has(self, key: K) -> bool: 205 """ 206 @private Return True when *key* exists in the set. 207 208 Example:: 209 210 s = TreeMultiSet([1, 2, 3]) 211 s.has(1) # True 212 s.has(4) # False 213 214 """ 215 it = self._t.find(key) 216 return not it.equals(self._t.end()) 217 218 def keys(self) -> PyIterator[K]: 219 """ 220 @private Return a forward iterator over all keys in ascending order. 221 222 Example:: 223 224 s = TreeMultiSet([1, 2, 2, 3]) 225 list(s.keys()) # [1, 2, 2, 3] 226 227 """ 228 return self._t.keys() 229 230 @property 231 def size(self) -> int: 232 """ 233 @private Number of elements (counting duplicates) in the set. 234 235 Example:: 236 237 s = TreeMultiSet([1, 2, 2, 3]) 238 s.size # 4 239 240 """ 241 return self._t.size() 242 243 def __contains__(self, key: K) -> bool: 244 """ 245 Return True when *key* is in the set. 246 247 Example:: 248 249 s = TreeMultiSet([1, 2, 3]) 250 1 in s # True 251 4 not in s # True 252 253 """ 254 return self.has(key) 255 256 def __iter__(self) -> PyIterator[K]: 257 """ 258 Iterate over all keys in ascending order (duplicates included). 259 260 Example:: 261 262 s = TreeMultiSet([1, 2, 2, 3]) 263 list(s) # [1, 2, 2, 3] 264 265 """ 266 return self._t.keys() 267 268 def __len__(self) -> int: 269 """ 270 Return the total number of elements (counting duplicates). 271 272 Example:: 273 274 s = TreeMultiSet([1, 2, 2]) 275 len(s) # 3 276 277 """ 278 return self._t.size() 279 280 def __str__(self) -> str: 281 """ 282 Return a string representation in the form {key1,key2,...}. 283 284 Example:: 285 286 s = TreeMultiSet([1, 2, 2, 3]) 287 str(s) # "{1,2,2,3}" 288 289 """ 290 return str(self._t) 291 292 def __repr__(self) -> str: 293 """ 294 Return a string representation in the form {key1,key2,...}. 295 296 Example:: 297 298 s = TreeMultiSet([1, 2, 2, 3]) 299 str(s) # "{1,2,2,3}" 300 301 """ 302 return self.__str__() 303 304 # ------------------------------------------------------------------ 305 # Additional iteration 306 # ------------------------------------------------------------------ 307 308 def backwards(self) -> PyReverseIterator[K]: 309 """ 310 Return a reverse iterator over all keys in descending order. 311 312 Example:: 313 314 s = TreeMultiSet([1, 2, 3]) 315 list(s.backwards()) # [3, 2, 1] 316 317 """ 318 return self._t.keys().backwards() 319 320 # ------------------------------------------------------------------ 321 # Custom comparator 322 # ------------------------------------------------------------------ 323 324 @property 325 def compare_func(self) -> Callable[[Any, Any], int]: 326 """ 327 @private The current 3-way comparison function used to order keys. 328 329 Setting this property clears all existing elements. 330 331 Example:: 332 333 s = TreeMultiSet() 334 s.compare_func = lambda a, b: -1 if a < b else (1 if a > b else 0) 335 336 """ 337 return self._t.compare 338 339 @compare_func.setter 340 def compare_func(self, func: Callable[[Any, Any], int]) -> None: 341 """@private Replace the comparison function and clear all elements.""" 342 self.clear() 343 self._t.compare = func 344 345 # ------------------------------------------------------------------ 346 # STL-style iterators 347 # ------------------------------------------------------------------ 348 349 def begin(self) -> TreeIterator[K, K]: 350 """ 351 Return a forward STL-like iterator to the first element. 352 353 Example:: 354 355 s = TreeMultiSet([1, 2, 3]) 356 it = s.begin() 357 while not it.equals(s.end()): 358 print(it.key) 359 it.next() 360 # 1, 2, 3 361 362 """ 363 return self._t.begin() 364 365 def end(self) -> TreeIterator[K, K]: 366 """ 367 Return a forward STL-like iterator past the last element. 368 369 Example:: 370 371 s = TreeMultiSet([1, 2, 3]) 372 it = s.begin() 373 while not it.equals(s.end()): 374 print(it.key) 375 it.next() 376 377 """ 378 return self._t.end() 379 380 def find(self, key: K) -> TreeIterator[K, K]: 381 """ 382 Return an STL-like iterator to an element with *key*, or end() if absent. 383 384 Example:: 385 386 s = TreeMultiSet([1, 2, 2, 3]) 387 it = s.find(2) 388 if not it.equals(s.end()): 389 print(it.key) # 2 390 391 """ 392 return self._t.find(key) 393 394 def insert_unique(self, key: K) -> InsertionResult[TreeIterator[K, K]]: 395 """ 396 Insert *key* only when it is not already present. 397 398 Returns: 399 InsertionResult with was_added=True when the key was new. 400 401 Example:: 402 403 s = TreeMultiSet() 404 res = s.insert_unique(1) 405 res.was_added # True 406 res2 = s.insert_unique(1) 407 res2.was_added # False 408 s.size # 1 409 410 """ 411 n: TreeNode[K, K] = TreeNode() 412 n.key = key 413 return self._t.insert_unique(n) 414 415 def insert_or_replace(self, key: K) -> InsertionResult[TreeIterator[K, K]]: 416 """ 417 Insert *key* if absent; if present, replace in-place. 418 419 Returns: 420 InsertionResult with was_added=True on new insertion, or 421 was_replaced=True when the key already existed. 422 423 Example:: 424 425 s = TreeMultiSet() 426 res = s.insert_or_replace(1) 427 res.was_added # True 428 res2 = s.insert_or_replace(1) 429 res2.was_replaced # True 430 s.size # 1 431 432 """ 433 n: TreeNode[K, K] = TreeNode() 434 n.key = key 435 return self._t.insert_or_replace(n) 436 437 def insert_multi(self, key: K) -> InsertionResult[TreeIterator[K, K]]: 438 """ 439 Insert *key* unconditionally, even when an equal key already exists. 440 441 Returns: 442 InsertionResult always with was_added=True. 443 444 Example:: 445 446 s = TreeMultiSet() 447 s.insert_multi(1) 448 s.insert_multi(1) 449 s.size # 2 450 451 """ 452 n: TreeNode[K, K] = TreeNode() 453 n.key = key 454 return self._t.insert_multi(n) 455 456 def erase(self, iterator: TreeIterator[K, K]) -> None: 457 """ 458 Remove the element pointed to by *iterator*. 459 460 Example:: 461 462 s = TreeMultiSet([1, 2, 3]) 463 it = s.find(2) 464 it.prev() 465 s.erase(it) # removes element with key 1 466 str(s) # "{2,3}" 467 468 """ 469 self._t.erase(iterator.node) 470 471 def lower_bound(self, key: K) -> TreeIterator[K, K]: 472 """ 473 Return an STL-like iterator to the first element with key >= *key*, or end(). 474 475 Example:: 476 477 s = TreeMultiSet([2, 4, 4, 6]) 478 lo = s.lower_bound(3) # iterator to first 4 479 hi = s.upper_bound(4) # iterator past last 4 480 it = lo 481 while not it.equals(hi): 482 print(it.key) # 4, 4 483 it.next() 484 485 """ 486 return self._t.lower_bound(key) 487 488 def rbegin(self) -> ReverseIterator[K, K]: 489 """ 490 Return a reverse STL-like iterator to the element with the largest key. 491 492 Example:: 493 494 s = TreeMultiSet([1, 2, 3]) 495 it = s.rbegin() 496 while not it.equals(s.rend()): 497 print(it.key) # 3, 2, 1 498 it.next() 499 500 """ 501 return self._t.rbegin() 502 503 def rend(self) -> ReverseIterator[K, K]: 504 """ 505 Return a reverse STL-like iterator before the element with the smallest key. 506 507 Example:: 508 509 s = TreeMultiSet([1, 2, 3]) 510 it = s.rbegin() 511 while not it.equals(s.rend()): 512 print(it.key) # 3 2 1 513 it.next() 514 515 """ 516 return self._t.rend() 517 518 def upper_bound(self, key: K) -> TreeIterator[K, K]: 519 """ 520 Return an STL-like iterator to the first element with key > *key*, or end(). 521 522 Example:: 523 524 s = TreeMultiSet([2, 4, 4, 6]) 525 lo = s.lower_bound(3) 526 hi = s.upper_bound(4) 527 it = lo 528 while not it.equals(hi): 529 print(it.key) # 4, 4 530 it.next() 531 532 """ 533 return self._t.upper_bound(key) 534 535 def first(self) -> K | None: 536 """ 537 Return the smallest element, or None when the set is empty. 538 539 Example:: 540 541 s = TreeMultiSet([1, 1, 2, 3]) 542 s.first() # 1 543 TreeMultiSet().first() # None 544 545 """ 546 return self._t.first() # type: ignore[return-value] 547 548 def last(self) -> K | None: 549 """ 550 Return the largest element, or None when the set is empty. 551 552 Example:: 553 554 s = TreeMultiSet([1, 2, 3, 3]) 555 s.last() # 3 556 TreeMultiSet().last() # None 557 558 """ 559 return self._t.last() # type: ignore[return-value]
17class TreeMultiSet[K]: 18 """ 19 Ordered multiset of keys backed by a red-black tree. 20 21 Unlike TreeSet, multiple equal keys are allowed. Elements are kept in 22 ascending order. Lookup, insertion, and deletion are all O(log n). 23 24 Example:: 25 26 s = TreeMultiSet() 27 s.add(1) 28 s.add(2) 29 s.add(2) 30 for key in s: 31 print(key) # 1, 2, 2 32 """ 33 34 def __init__(self, iterable: Iterable[K] | None = None, *args) -> None: 35 """ 36 Create an empty multiset, or pre-populate it from an iterable of keys. 37 38 Duplicate keys are preserved (multiset semantics). 39 40 Args: 41 iterable: Optional iterable of keys. 42 args: initial keys could be provided as extra parameters 43 44 Raises: 45 TypeError: When *iterable* is not iterable. 46 47 Example:: 48 49 s = TreeMultiSet() 50 s = TreeMultiSet([1, 2, 2, 3]) # {1,2,2,3} 51 s = TreeMultiSet({1, 2}) # {1,2} 52 s = TreeMultiSet(None, 1, 2, 1, 2) # {1,1,2,2} 53 54 """ 55 self._t: Tree[K, K] = Tree() 56 self._t.value_policy = KeyOnlyPolicy() 57 if iterable is not None: 58 self.update(iterable) 59 if args: 60 self.update(args) 61 62 def update(self, *iterables: Iterable[K]) -> None: 63 """ 64 Add contents from all provided iterables to the current set. 65 66 Duplicate keys are preserved (multiset semantics). 67 68 Args: 69 iterables: One or more iterables containing keys. 70 71 Raises: 72 TypeError: When *iterable* is not iterable. 73 74 Example:: 75 76 s = TreeMultiSet() 77 s.update([1, 2, 2, 3]) # {1,2,2,3} 78 79 """ 80 for iterable in iterables: 81 if not hasattr(iterable, "__iter__"): 82 raise TypeError("TreeMultiSet accepts only iterable objects") 83 for k in iterable: 84 self.add(k) 85 86 # ------------------------------------------------------------------ 87 # Core mutation 88 # ------------------------------------------------------------------ 89 90 def clear(self) -> None: 91 """ 92 Remove all elements. 93 94 Example:: 95 96 s = TreeMultiSet([1, 2, 3]) 97 s.clear() 98 len(s) # 0 99 100 """ 101 self._t.clear() 102 103 def add(self, key: K) -> None: 104 """ 105 Insert *key*, always adding a new entry even if an equal key exists. 106 107 Example:: 108 109 s = TreeMultiSet() 110 s.add(1) 111 s.add(1) 112 len(s) # 2 113 114 """ 115 n: TreeNode[K, K] = TreeNode() 116 n.key = key 117 self._t.insert_multi(n) 118 119 def discard(self, key: K) -> None: 120 """ 121 Remove one occurrence of *key* if present; do nothing when absent. 122 123 Example:: 124 125 s = TreeMultiSet([1, 2, 2, 3]) 126 s.discard(2) # s is now {1,2,3} 127 s.discard(99) # no-op 128 129 """ 130 it = self._t.find(key) 131 if not it.equals(self._t.end()): 132 self._t.erase(it.node) 133 134 def remove(self, key: K) -> None: 135 """ 136 Remove one occurrence of *key*, raising KeyError when absent. 137 138 Args: 139 key: Key to remove. 140 141 Raises: 142 KeyError: When *key* is not present. 143 144 Example:: 145 146 s = TreeMultiSet([1, 2, 2, 3]) 147 s.remove(2) # s is now {1,2,3} 148 s.remove(99) # raises KeyError 149 150 """ 151 it = self._t.find(key) 152 if not it.equals(self._t.end()): 153 self._t.erase(it.node) 154 else: 155 raise KeyError(key) 156 157 def delete(self, key: K) -> None: 158 """ 159 @private Remove one occurrence of *key* if present; alias for discard(). 160 161 Example:: 162 163 s = TreeMultiSet([1, 2, 2, 3]) 164 s.delete(2) # s is now {1,2,3} 165 s.delete(99) # no-op 166 167 """ 168 self.discard(key) 169 170 def pop(self, key: K | None = None, default: K | None = None) -> K | None: 171 """ 172 Remove one occurrence of *key* and return it, or return *default* when absent. 173 174 When called with no arguments, removes and returns the smallest element. 175 176 Args: 177 key: Key to remove. When None, the smallest element is removed. 178 default: Value to return when *key* is absent. 179 180 Raises: 181 KeyError: When called with no arguments on an empty set. 182 183 Example:: 184 185 s = TreeMultiSet([1, 2, 2, 3]) 186 s.pop(2) # 2, s is now {1,2,3} 187 s.pop(9) # None 188 s.pop(9, 0) # 0 189 s.pop() # 1 — removes and returns smallest element 190 191 """ 192 if self.size == 0: 193 raise KeyError("pop from an empty set") 194 it = self._t.find(key) if key is not None else self.begin() 195 if not it.equals(self._t.end()): 196 k = it.key 197 self._t.erase(it.node) 198 return k 199 return default 200 201 # ------------------------------------------------------------------ 202 # Queries 203 # ------------------------------------------------------------------ 204 205 def has(self, key: K) -> bool: 206 """ 207 @private Return True when *key* exists in the set. 208 209 Example:: 210 211 s = TreeMultiSet([1, 2, 3]) 212 s.has(1) # True 213 s.has(4) # False 214 215 """ 216 it = self._t.find(key) 217 return not it.equals(self._t.end()) 218 219 def keys(self) -> PyIterator[K]: 220 """ 221 @private Return a forward iterator over all keys in ascending order. 222 223 Example:: 224 225 s = TreeMultiSet([1, 2, 2, 3]) 226 list(s.keys()) # [1, 2, 2, 3] 227 228 """ 229 return self._t.keys() 230 231 @property 232 def size(self) -> int: 233 """ 234 @private Number of elements (counting duplicates) in the set. 235 236 Example:: 237 238 s = TreeMultiSet([1, 2, 2, 3]) 239 s.size # 4 240 241 """ 242 return self._t.size() 243 244 def __contains__(self, key: K) -> bool: 245 """ 246 Return True when *key* is in the set. 247 248 Example:: 249 250 s = TreeMultiSet([1, 2, 3]) 251 1 in s # True 252 4 not in s # True 253 254 """ 255 return self.has(key) 256 257 def __iter__(self) -> PyIterator[K]: 258 """ 259 Iterate over all keys in ascending order (duplicates included). 260 261 Example:: 262 263 s = TreeMultiSet([1, 2, 2, 3]) 264 list(s) # [1, 2, 2, 3] 265 266 """ 267 return self._t.keys() 268 269 def __len__(self) -> int: 270 """ 271 Return the total number of elements (counting duplicates). 272 273 Example:: 274 275 s = TreeMultiSet([1, 2, 2]) 276 len(s) # 3 277 278 """ 279 return self._t.size() 280 281 def __str__(self) -> str: 282 """ 283 Return a string representation in the form {key1,key2,...}. 284 285 Example:: 286 287 s = TreeMultiSet([1, 2, 2, 3]) 288 str(s) # "{1,2,2,3}" 289 290 """ 291 return str(self._t) 292 293 def __repr__(self) -> str: 294 """ 295 Return a string representation in the form {key1,key2,...}. 296 297 Example:: 298 299 s = TreeMultiSet([1, 2, 2, 3]) 300 str(s) # "{1,2,2,3}" 301 302 """ 303 return self.__str__() 304 305 # ------------------------------------------------------------------ 306 # Additional iteration 307 # ------------------------------------------------------------------ 308 309 def backwards(self) -> PyReverseIterator[K]: 310 """ 311 Return a reverse iterator over all keys in descending order. 312 313 Example:: 314 315 s = TreeMultiSet([1, 2, 3]) 316 list(s.backwards()) # [3, 2, 1] 317 318 """ 319 return self._t.keys().backwards() 320 321 # ------------------------------------------------------------------ 322 # Custom comparator 323 # ------------------------------------------------------------------ 324 325 @property 326 def compare_func(self) -> Callable[[Any, Any], int]: 327 """ 328 @private The current 3-way comparison function used to order keys. 329 330 Setting this property clears all existing elements. 331 332 Example:: 333 334 s = TreeMultiSet() 335 s.compare_func = lambda a, b: -1 if a < b else (1 if a > b else 0) 336 337 """ 338 return self._t.compare 339 340 @compare_func.setter 341 def compare_func(self, func: Callable[[Any, Any], int]) -> None: 342 """@private Replace the comparison function and clear all elements.""" 343 self.clear() 344 self._t.compare = func 345 346 # ------------------------------------------------------------------ 347 # STL-style iterators 348 # ------------------------------------------------------------------ 349 350 def begin(self) -> TreeIterator[K, K]: 351 """ 352 Return a forward STL-like iterator to the first element. 353 354 Example:: 355 356 s = TreeMultiSet([1, 2, 3]) 357 it = s.begin() 358 while not it.equals(s.end()): 359 print(it.key) 360 it.next() 361 # 1, 2, 3 362 363 """ 364 return self._t.begin() 365 366 def end(self) -> TreeIterator[K, K]: 367 """ 368 Return a forward STL-like iterator past the last element. 369 370 Example:: 371 372 s = TreeMultiSet([1, 2, 3]) 373 it = s.begin() 374 while not it.equals(s.end()): 375 print(it.key) 376 it.next() 377 378 """ 379 return self._t.end() 380 381 def find(self, key: K) -> TreeIterator[K, K]: 382 """ 383 Return an STL-like iterator to an element with *key*, or end() if absent. 384 385 Example:: 386 387 s = TreeMultiSet([1, 2, 2, 3]) 388 it = s.find(2) 389 if not it.equals(s.end()): 390 print(it.key) # 2 391 392 """ 393 return self._t.find(key) 394 395 def insert_unique(self, key: K) -> InsertionResult[TreeIterator[K, K]]: 396 """ 397 Insert *key* only when it is not already present. 398 399 Returns: 400 InsertionResult with was_added=True when the key was new. 401 402 Example:: 403 404 s = TreeMultiSet() 405 res = s.insert_unique(1) 406 res.was_added # True 407 res2 = s.insert_unique(1) 408 res2.was_added # False 409 s.size # 1 410 411 """ 412 n: TreeNode[K, K] = TreeNode() 413 n.key = key 414 return self._t.insert_unique(n) 415 416 def insert_or_replace(self, key: K) -> InsertionResult[TreeIterator[K, K]]: 417 """ 418 Insert *key* if absent; if present, replace in-place. 419 420 Returns: 421 InsertionResult with was_added=True on new insertion, or 422 was_replaced=True when the key already existed. 423 424 Example:: 425 426 s = TreeMultiSet() 427 res = s.insert_or_replace(1) 428 res.was_added # True 429 res2 = s.insert_or_replace(1) 430 res2.was_replaced # True 431 s.size # 1 432 433 """ 434 n: TreeNode[K, K] = TreeNode() 435 n.key = key 436 return self._t.insert_or_replace(n) 437 438 def insert_multi(self, key: K) -> InsertionResult[TreeIterator[K, K]]: 439 """ 440 Insert *key* unconditionally, even when an equal key already exists. 441 442 Returns: 443 InsertionResult always with was_added=True. 444 445 Example:: 446 447 s = TreeMultiSet() 448 s.insert_multi(1) 449 s.insert_multi(1) 450 s.size # 2 451 452 """ 453 n: TreeNode[K, K] = TreeNode() 454 n.key = key 455 return self._t.insert_multi(n) 456 457 def erase(self, iterator: TreeIterator[K, K]) -> None: 458 """ 459 Remove the element pointed to by *iterator*. 460 461 Example:: 462 463 s = TreeMultiSet([1, 2, 3]) 464 it = s.find(2) 465 it.prev() 466 s.erase(it) # removes element with key 1 467 str(s) # "{2,3}" 468 469 """ 470 self._t.erase(iterator.node) 471 472 def lower_bound(self, key: K) -> TreeIterator[K, K]: 473 """ 474 Return an STL-like iterator to the first element with key >= *key*, or end(). 475 476 Example:: 477 478 s = TreeMultiSet([2, 4, 4, 6]) 479 lo = s.lower_bound(3) # iterator to first 4 480 hi = s.upper_bound(4) # iterator past last 4 481 it = lo 482 while not it.equals(hi): 483 print(it.key) # 4, 4 484 it.next() 485 486 """ 487 return self._t.lower_bound(key) 488 489 def rbegin(self) -> ReverseIterator[K, K]: 490 """ 491 Return a reverse STL-like iterator to the element with the largest key. 492 493 Example:: 494 495 s = TreeMultiSet([1, 2, 3]) 496 it = s.rbegin() 497 while not it.equals(s.rend()): 498 print(it.key) # 3, 2, 1 499 it.next() 500 501 """ 502 return self._t.rbegin() 503 504 def rend(self) -> ReverseIterator[K, K]: 505 """ 506 Return a reverse STL-like iterator before the element with the smallest key. 507 508 Example:: 509 510 s = TreeMultiSet([1, 2, 3]) 511 it = s.rbegin() 512 while not it.equals(s.rend()): 513 print(it.key) # 3 2 1 514 it.next() 515 516 """ 517 return self._t.rend() 518 519 def upper_bound(self, key: K) -> TreeIterator[K, K]: 520 """ 521 Return an STL-like iterator to the first element with key > *key*, or end(). 522 523 Example:: 524 525 s = TreeMultiSet([2, 4, 4, 6]) 526 lo = s.lower_bound(3) 527 hi = s.upper_bound(4) 528 it = lo 529 while not it.equals(hi): 530 print(it.key) # 4, 4 531 it.next() 532 533 """ 534 return self._t.upper_bound(key) 535 536 def first(self) -> K | None: 537 """ 538 Return the smallest element, or None when the set is empty. 539 540 Example:: 541 542 s = TreeMultiSet([1, 1, 2, 3]) 543 s.first() # 1 544 TreeMultiSet().first() # None 545 546 """ 547 return self._t.first() # type: ignore[return-value] 548 549 def last(self) -> K | None: 550 """ 551 Return the largest element, or None when the set is empty. 552 553 Example:: 554 555 s = TreeMultiSet([1, 2, 3, 3]) 556 s.last() # 3 557 TreeMultiSet().last() # None 558 559 """ 560 return self._t.last() # type: ignore[return-value]
Ordered multiset of keys backed by a red-black tree.
Unlike TreeSet, multiple equal keys are allowed. Elements are kept in ascending order. Lookup, insertion, and deletion are all O(log n).
Example::
s = TreeMultiSet()
s.add(1)
s.add(2)
s.add(2)
for key in s:
print(key) # 1, 2, 2
34 def __init__(self, iterable: Iterable[K] | None = None, *args) -> None: 35 """ 36 Create an empty multiset, or pre-populate it from an iterable of keys. 37 38 Duplicate keys are preserved (multiset semantics). 39 40 Args: 41 iterable: Optional iterable of keys. 42 args: initial keys could be provided as extra parameters 43 44 Raises: 45 TypeError: When *iterable* is not iterable. 46 47 Example:: 48 49 s = TreeMultiSet() 50 s = TreeMultiSet([1, 2, 2, 3]) # {1,2,2,3} 51 s = TreeMultiSet({1, 2}) # {1,2} 52 s = TreeMultiSet(None, 1, 2, 1, 2) # {1,1,2,2} 53 54 """ 55 self._t: Tree[K, K] = Tree() 56 self._t.value_policy = KeyOnlyPolicy() 57 if iterable is not None: 58 self.update(iterable) 59 if args: 60 self.update(args)
Create an empty multiset, or pre-populate it from an iterable of keys.
Duplicate keys are preserved (multiset semantics).
Args: iterable: Optional iterable of keys. args: initial keys could be provided as extra parameters
Raises: TypeError: When iterable is not iterable.
Example::
s = TreeMultiSet()
s = TreeMultiSet([1, 2, 2, 3]) # {1,2,2,3}
s = TreeMultiSet({1, 2}) # {1,2}
s = TreeMultiSet(None, 1, 2, 1, 2) # {1,1,2,2}
62 def update(self, *iterables: Iterable[K]) -> None: 63 """ 64 Add contents from all provided iterables to the current set. 65 66 Duplicate keys are preserved (multiset semantics). 67 68 Args: 69 iterables: One or more iterables containing keys. 70 71 Raises: 72 TypeError: When *iterable* is not iterable. 73 74 Example:: 75 76 s = TreeMultiSet() 77 s.update([1, 2, 2, 3]) # {1,2,2,3} 78 79 """ 80 for iterable in iterables: 81 if not hasattr(iterable, "__iter__"): 82 raise TypeError("TreeMultiSet accepts only iterable objects") 83 for k in iterable: 84 self.add(k)
Add contents from all provided iterables to the current set.
Duplicate keys are preserved (multiset semantics).
Args: iterables: One or more iterables containing keys.
Raises: TypeError: When iterable is not iterable.
Example::
s = TreeMultiSet()
s.update([1, 2, 2, 3]) # {1,2,2,3}
90 def clear(self) -> None: 91 """ 92 Remove all elements. 93 94 Example:: 95 96 s = TreeMultiSet([1, 2, 3]) 97 s.clear() 98 len(s) # 0 99 100 """ 101 self._t.clear()
Remove all elements.
Example::
s = TreeMultiSet([1, 2, 3])
s.clear()
len(s) # 0
103 def add(self, key: K) -> None: 104 """ 105 Insert *key*, always adding a new entry even if an equal key exists. 106 107 Example:: 108 109 s = TreeMultiSet() 110 s.add(1) 111 s.add(1) 112 len(s) # 2 113 114 """ 115 n: TreeNode[K, K] = TreeNode() 116 n.key = key 117 self._t.insert_multi(n)
Insert key, always adding a new entry even if an equal key exists.
Example::
s = TreeMultiSet()
s.add(1)
s.add(1)
len(s) # 2
119 def discard(self, key: K) -> None: 120 """ 121 Remove one occurrence of *key* if present; do nothing when absent. 122 123 Example:: 124 125 s = TreeMultiSet([1, 2, 2, 3]) 126 s.discard(2) # s is now {1,2,3} 127 s.discard(99) # no-op 128 129 """ 130 it = self._t.find(key) 131 if not it.equals(self._t.end()): 132 self._t.erase(it.node)
Remove one occurrence of key if present; do nothing when absent.
Example::
s = TreeMultiSet([1, 2, 2, 3])
s.discard(2) # s is now {1,2,3}
s.discard(99) # no-op
134 def remove(self, key: K) -> None: 135 """ 136 Remove one occurrence of *key*, raising KeyError when absent. 137 138 Args: 139 key: Key to remove. 140 141 Raises: 142 KeyError: When *key* is not present. 143 144 Example:: 145 146 s = TreeMultiSet([1, 2, 2, 3]) 147 s.remove(2) # s is now {1,2,3} 148 s.remove(99) # raises KeyError 149 150 """ 151 it = self._t.find(key) 152 if not it.equals(self._t.end()): 153 self._t.erase(it.node) 154 else: 155 raise KeyError(key)
Remove one occurrence of key, raising KeyError when absent.
Args: key: Key to remove.
Raises: KeyError: When key is not present.
Example::
s = TreeMultiSet([1, 2, 2, 3])
s.remove(2) # s is now {1,2,3}
s.remove(99) # raises KeyError
170 def pop(self, key: K | None = None, default: K | None = None) -> K | None: 171 """ 172 Remove one occurrence of *key* and return it, or return *default* when absent. 173 174 When called with no arguments, removes and returns the smallest element. 175 176 Args: 177 key: Key to remove. When None, the smallest element is removed. 178 default: Value to return when *key* is absent. 179 180 Raises: 181 KeyError: When called with no arguments on an empty set. 182 183 Example:: 184 185 s = TreeMultiSet([1, 2, 2, 3]) 186 s.pop(2) # 2, s is now {1,2,3} 187 s.pop(9) # None 188 s.pop(9, 0) # 0 189 s.pop() # 1 — removes and returns smallest element 190 191 """ 192 if self.size == 0: 193 raise KeyError("pop from an empty set") 194 it = self._t.find(key) if key is not None else self.begin() 195 if not it.equals(self._t.end()): 196 k = it.key 197 self._t.erase(it.node) 198 return k 199 return default
Remove one occurrence of key and return it, or return default when absent.
When called with no arguments, removes and returns the smallest element.
Args: key: Key to remove. When None, the smallest element is removed. default: Value to return when key is absent.
Raises: KeyError: When called with no arguments on an empty set.
Example::
s = TreeMultiSet([1, 2, 2, 3])
s.pop(2) # 2, s is now {1,2,3}
s.pop(9) # None
s.pop(9, 0) # 0
s.pop() # 1 — removes and returns smallest element
309 def backwards(self) -> PyReverseIterator[K]: 310 """ 311 Return a reverse iterator over all keys in descending order. 312 313 Example:: 314 315 s = TreeMultiSet([1, 2, 3]) 316 list(s.backwards()) # [3, 2, 1] 317 318 """ 319 return self._t.keys().backwards()
Return a reverse iterator over all keys in descending order.
Example::
s = TreeMultiSet([1, 2, 3])
list(s.backwards()) # [3, 2, 1]
350 def begin(self) -> TreeIterator[K, K]: 351 """ 352 Return a forward STL-like iterator to the first element. 353 354 Example:: 355 356 s = TreeMultiSet([1, 2, 3]) 357 it = s.begin() 358 while not it.equals(s.end()): 359 print(it.key) 360 it.next() 361 # 1, 2, 3 362 363 """ 364 return self._t.begin()
Return a forward STL-like iterator to the first element.
Example::
s = TreeMultiSet([1, 2, 3])
it = s.begin()
while not it.equals(s.end()):
print(it.key)
it.next()
# 1, 2, 3
366 def end(self) -> TreeIterator[K, K]: 367 """ 368 Return a forward STL-like iterator past the last element. 369 370 Example:: 371 372 s = TreeMultiSet([1, 2, 3]) 373 it = s.begin() 374 while not it.equals(s.end()): 375 print(it.key) 376 it.next() 377 378 """ 379 return self._t.end()
Return a forward STL-like iterator past the last element.
Example::
s = TreeMultiSet([1, 2, 3])
it = s.begin()
while not it.equals(s.end()):
print(it.key)
it.next()
381 def find(self, key: K) -> TreeIterator[K, K]: 382 """ 383 Return an STL-like iterator to an element with *key*, or end() if absent. 384 385 Example:: 386 387 s = TreeMultiSet([1, 2, 2, 3]) 388 it = s.find(2) 389 if not it.equals(s.end()): 390 print(it.key) # 2 391 392 """ 393 return self._t.find(key)
Return an STL-like iterator to an element with key, or end() if absent.
Example::
s = TreeMultiSet([1, 2, 2, 3])
it = s.find(2)
if not it.equals(s.end()):
print(it.key) # 2
395 def insert_unique(self, key: K) -> InsertionResult[TreeIterator[K, K]]: 396 """ 397 Insert *key* only when it is not already present. 398 399 Returns: 400 InsertionResult with was_added=True when the key was new. 401 402 Example:: 403 404 s = TreeMultiSet() 405 res = s.insert_unique(1) 406 res.was_added # True 407 res2 = s.insert_unique(1) 408 res2.was_added # False 409 s.size # 1 410 411 """ 412 n: TreeNode[K, K] = TreeNode() 413 n.key = key 414 return self._t.insert_unique(n)
Insert key only when it is not already present.
Returns: InsertionResult with was_added=True when the key was new.
Example::
s = TreeMultiSet()
res = s.insert_unique(1)
res.was_added # True
res2 = s.insert_unique(1)
res2.was_added # False
s.size # 1
416 def insert_or_replace(self, key: K) -> InsertionResult[TreeIterator[K, K]]: 417 """ 418 Insert *key* if absent; if present, replace in-place. 419 420 Returns: 421 InsertionResult with was_added=True on new insertion, or 422 was_replaced=True when the key already existed. 423 424 Example:: 425 426 s = TreeMultiSet() 427 res = s.insert_or_replace(1) 428 res.was_added # True 429 res2 = s.insert_or_replace(1) 430 res2.was_replaced # True 431 s.size # 1 432 433 """ 434 n: TreeNode[K, K] = TreeNode() 435 n.key = key 436 return self._t.insert_or_replace(n)
Insert key if absent; if present, replace in-place.
Returns: InsertionResult with was_added=True on new insertion, or was_replaced=True when the key already existed.
Example::
s = TreeMultiSet()
res = s.insert_or_replace(1)
res.was_added # True
res2 = s.insert_or_replace(1)
res2.was_replaced # True
s.size # 1
438 def insert_multi(self, key: K) -> InsertionResult[TreeIterator[K, K]]: 439 """ 440 Insert *key* unconditionally, even when an equal key already exists. 441 442 Returns: 443 InsertionResult always with was_added=True. 444 445 Example:: 446 447 s = TreeMultiSet() 448 s.insert_multi(1) 449 s.insert_multi(1) 450 s.size # 2 451 452 """ 453 n: TreeNode[K, K] = TreeNode() 454 n.key = key 455 return self._t.insert_multi(n)
Insert key unconditionally, even when an equal key already exists.
Returns: InsertionResult always with was_added=True.
Example::
s = TreeMultiSet()
s.insert_multi(1)
s.insert_multi(1)
s.size # 2
457 def erase(self, iterator: TreeIterator[K, K]) -> None: 458 """ 459 Remove the element pointed to by *iterator*. 460 461 Example:: 462 463 s = TreeMultiSet([1, 2, 3]) 464 it = s.find(2) 465 it.prev() 466 s.erase(it) # removes element with key 1 467 str(s) # "{2,3}" 468 469 """ 470 self._t.erase(iterator.node)
Remove the element pointed to by iterator.
Example::
s = TreeMultiSet([1, 2, 3])
it = s.find(2)
it.prev()
s.erase(it) # removes element with key 1
str(s) # "{2,3}"
472 def lower_bound(self, key: K) -> TreeIterator[K, K]: 473 """ 474 Return an STL-like iterator to the first element with key >= *key*, or end(). 475 476 Example:: 477 478 s = TreeMultiSet([2, 4, 4, 6]) 479 lo = s.lower_bound(3) # iterator to first 4 480 hi = s.upper_bound(4) # iterator past last 4 481 it = lo 482 while not it.equals(hi): 483 print(it.key) # 4, 4 484 it.next() 485 486 """ 487 return self._t.lower_bound(key)
Return an STL-like iterator to the first element with key >= key, or end().
Example::
s = TreeMultiSet([2, 4, 4, 6])
lo = s.lower_bound(3) # iterator to first 4
hi = s.upper_bound(4) # iterator past last 4
it = lo
while not it.equals(hi):
print(it.key) # 4, 4
it.next()
489 def rbegin(self) -> ReverseIterator[K, K]: 490 """ 491 Return a reverse STL-like iterator to the element with the largest key. 492 493 Example:: 494 495 s = TreeMultiSet([1, 2, 3]) 496 it = s.rbegin() 497 while not it.equals(s.rend()): 498 print(it.key) # 3, 2, 1 499 it.next() 500 501 """ 502 return self._t.rbegin()
Return a reverse STL-like iterator to the element with the largest key.
Example::
s = TreeMultiSet([1, 2, 3])
it = s.rbegin()
while not it.equals(s.rend()):
print(it.key) # 3, 2, 1
it.next()
504 def rend(self) -> ReverseIterator[K, K]: 505 """ 506 Return a reverse STL-like iterator before the element with the smallest key. 507 508 Example:: 509 510 s = TreeMultiSet([1, 2, 3]) 511 it = s.rbegin() 512 while not it.equals(s.rend()): 513 print(it.key) # 3 2 1 514 it.next() 515 516 """ 517 return self._t.rend()
Return a reverse STL-like iterator before the element with the smallest key.
Example::
s = TreeMultiSet([1, 2, 3])
it = s.rbegin()
while not it.equals(s.rend()):
print(it.key) # 3 2 1
it.next()
519 def upper_bound(self, key: K) -> TreeIterator[K, K]: 520 """ 521 Return an STL-like iterator to the first element with key > *key*, or end(). 522 523 Example:: 524 525 s = TreeMultiSet([2, 4, 4, 6]) 526 lo = s.lower_bound(3) 527 hi = s.upper_bound(4) 528 it = lo 529 while not it.equals(hi): 530 print(it.key) # 4, 4 531 it.next() 532 533 """ 534 return self._t.upper_bound(key)
Return an STL-like iterator to the first element with key > key, or end().
Example::
s = TreeMultiSet([2, 4, 4, 6])
lo = s.lower_bound(3)
hi = s.upper_bound(4)
it = lo
while not it.equals(hi):
print(it.key) # 4, 4
it.next()
536 def first(self) -> K | None: 537 """ 538 Return the smallest element, or None when the set is empty. 539 540 Example:: 541 542 s = TreeMultiSet([1, 1, 2, 3]) 543 s.first() # 1 544 TreeMultiSet().first() # None 545 546 """ 547 return self._t.first() # type: ignore[return-value]
Return the smallest element, or None when the set is empty.
Example::
s = TreeMultiSet([1, 1, 2, 3])
s.first() # 1
TreeMultiSet().first() # None
549 def last(self) -> K | None: 550 """ 551 Return the largest element, or None when the set is empty. 552 553 Example:: 554 555 s = TreeMultiSet([1, 2, 3, 3]) 556 s.last() # 3 557 TreeMultiSet().last() # None 558 559 """ 560 return self._t.last() # type: ignore[return-value]
Return the largest element, or None when the set is empty.
Example::
s = TreeMultiSet([1, 2, 3, 3])
s.last() # 3
TreeMultiSet().last() # None