Source code for titan_pylib.data_structures.heap.Randomized_meldable_heap

  1from typing import TypeVar, Generic, Iterable, Optional
  2
  3T = TypeVar("T")
  4
  5
[docs] 6class RandomizedMeldableHeap(Generic[T]): 7 """併合可能ヒープです。 8 9 [Randomized Meldable Heap](https://trap.jp/post/1050/), traP 10 """ 11 12 _x, _y, _z, _w = 123456789, 362436069, 521288629, 88675123 13
[docs] 14 class Node: 15 16 def __init__(self, key: T) -> None: 17 self.key = key 18 self.left = None 19 self.right = None
20 21 def __init__(self, a: Iterable[T] = []): 22 self.root = None 23 self.size = 0 24 self._build(a) 25 26 def _build(self, a: Iterable[T]) -> None: 27 a = sorted(a) 28 if not a: 29 return 30 n = len(a) 31 pool = [self.Node(e) for e in a] 32 for i in range(len(a)): 33 if i * 2 + 1 < n: 34 pool[i].left = pool[i * 2 + 1] 35 if i * 2 + 2 < n: 36 pool[i].right = pool[i * 2 + 2] 37 self.root = pool[0] 38 39 @classmethod 40 def _randbit(cls) -> int: 41 t = cls._x ^ (cls._x << 11) & 0xFFFFFFFF 42 cls._x, cls._y, cls._z = cls._y, cls._z, cls._w 43 cls._w = (cls._w ^ (cls._w >> 19)) ^ (t ^ (t >> 8)) & 0xFFFFFFFF 44 return cls._w & 1 45 46 @classmethod 47 def _meld(cls, x: Optional[Node], y: Optional[Node]) -> Optional[Node]: 48 if x is None: 49 return y 50 if y is None: 51 return x 52 if x.key > y.key: 53 x, y = y, x 54 if cls._randbit(): 55 x.left = cls._meld(x.left, y) 56 else: 57 x.right = cls._meld(x.right, y) 58 return x 59
[docs] 60 @classmethod 61 def meld( 62 cls, x: "RandomizedMeldableHeap", y: "RandomizedMeldableHeap" 63 ) -> "RandomizedMeldableHeap": 64 new_heap = RandomizedMeldableHeap() 65 new_heap.size = x.size + y.size 66 new_heap.root = cls._meld(x.root, y.root) 67 return new_heap
68
[docs] 69 def push(self, key: T) -> None: 70 node = RandomizedMeldableHeap.Node(key) 71 self.root = self._meld(self.root, node) 72 self.size += 1
73
[docs] 74 def pop_min(self) -> T: 75 res = self.root.key 76 self.root = self._meld(self.root.left, self.root.right) 77 return res
78
[docs] 79 def get_min(self) -> T: 80 return self.root.key
81
[docs] 82 def tolist(self) -> list[T]: 83 node = self.root 84 stack = [] 85 a = [] 86 while stack or node: 87 if node: 88 stack.append(node) 89 node = node.left 90 else: 91 node = stack.pop() 92 a.append(node.key) 93 node = node.right 94 a.sort() 95 return a
96 97 def __bool__(self): 98 return self.root is not None 99 100 def __len__(self): 101 return self.size 102 103 def __str__(self): 104 return str(self.tolist()) 105 106 def __repr__(self): 107 return f"{self.__class__.__name__}({self})"