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]
class TreeMultiSet(typing.Generic[K]):
 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
TreeMultiSet(iterable: 'Iterable[K] | None' = None, *args)
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}
def update(self, *iterables: 'Iterable[K]') -> None:
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}
def clear(self) -> None:
 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
def add(self, key: 'K') -> None:
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
def discard(self, key: 'K') -> None:
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
def remove(self, key: 'K') -> None:
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
def pop(self, key: 'K | None' = None, default: 'K | None' = None) -> 'K | None':
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
def backwards(self) -> 'PyReverseIterator[K]':
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]
def begin(self) -> 'TreeIterator[K, K]':
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
def end(self) -> 'TreeIterator[K, K]':
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()
def find(self, key: 'K') -> 'TreeIterator[K, K]':
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
def insert_unique(self, key: 'K') -> 'InsertionResult[TreeIterator[K, K]]':
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
def insert_or_replace(self, key: 'K') -> 'InsertionResult[TreeIterator[K, K]]':
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
def insert_multi(self, key: 'K') -> 'InsertionResult[TreeIterator[K, K]]':
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
def erase(self, iterator: 'TreeIterator[K, K]') -> None:
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}"
def lower_bound(self, key: 'K') -> 'TreeIterator[K, K]':
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()
def rbegin(self) -> 'ReverseIterator[K, K]':
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()
def rend(self) -> 'ReverseIterator[K, K]':
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()
def upper_bound(self, key: 'K') -> 'TreeIterator[K, K]':
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()
def first(self) -> 'K | None':
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
def last(self) -> 'K | 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