text: 8.5.
  heapq — Heap queue algorithm¶
  Source].:
  heapq.
  heappop(heap)¶
  Pop and return the smallest item from the heap, maintaining the heap invariant. If the heap is empty,
  IndexErroris raised. To access the smallest item without popping it, use
  heap[0].
  heapq.
  heappushpop(heap, item)¶
  Push item on the heap, then pop and return the smallest item from the heap. The combined action runs more efficiently than
  heappush()followed by a separate call to
  heappop().
  heapq.
  heapreplace(heap, item)¶
  Pop and return the smallest item from the heap, and also push the new item. The heap size doesn’t change. If the heap is empty,
  IndexError module also offers three general purpose functions based on heaps.
  heapq.
  merge(*iterables, key=None, reverse=False)¶).
  Has two optional arguments which must be specified as keyword arguments.
  key specifies a key function of one argument that is used to extract a comparison key from each input element. The default value is
  None(compare the elements directly).
  reverse is a boolean value. If set to
  True, then the input elements are merged as if each comparison were reversed. To achieve behavior similar to
  sorted(itertools.chain(*iterables), reverse=True), all iterables must be sorted from largest to smallest.
  Changed in version 3.5: Added the optional key and reverse parameters.
  heapq.
  nlargest(n, iterable, key=None)¶
  Return a list with the n largest elements from the dataset defined by iterable. key, if provided, specifies a function of one argument that is used to extract a comparison key from each element in the iterable:
  key=str.lowerEquivalent to:
  sorted(iterable, key=key, reverse=True)[:n]
  heapq.
  nsmallest(n, iterable, key=None)¶
  Return a list with the n smallest elements from the dataset defined by iterable. key, if provided, specifies a function of one argument that is used to extract a comparison key from each element in the iterable:
  key=str.lowerEquivalent to:
  sorted(iterable, key=key)[:n]
  The latter two functions perform best for smaller values of n. For larger
  values, it is more efficient to use the
  sorted() function. Also, when
  n==1, it is more efficient to use the built-in
  min() and
  max()
  functions. If repeated usage of these functions is required, consider turning
  the iterable into an actual heap.
  8.5.1. Basic Examples¶
  A heapsort can be implemented by pushing all values onto a heap and then popping off the smallest values one at a time:
  >>> def heapsort(iterable): ... h = [] ... for value in iterable: ... heappush(h, value) ... return [heappop(h) for i in range(len(h))] ... >>> heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0]) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  This is similar to
  sorted(iterable), but unlike
  sorted(), this
  implementation is not stable.')
  8.5.2. Priority Queue Implementation Notes¶
  A priority queue is common use for a heap, and it presents several implementation challenges:
  - Sort stability: how do you get two tasks with equal priorities to be returned in the order they were originally added?
  - Tuple comparison breaks for (priority, task) pairs if the priorities are equal and the tasks do not have a default comparison order.
  - If the priority of a task changes, how do you move it to a new position in the heap?
  - Or if a pending task needs to be deleted, how do you find it and remove it from the queue?.
  Another solution to the problem of non-comparable tasks is to create a wrapper class that ignores the task item and only compares the priority field:
  from dataclasses import dataclass, field from typing import Any @dataclass(order=True) class PrioritizedItem: priority: int item: Any=field(compare=False)')
  8.5.3. Theory¶ schedules, whose size is usually related to the amount of CPU memory), followed by a merging passes for these runs, which merging is often very cleverly organised [1]. It is very important that the initial sort produces the longest runs possible. Tournaments are a good way to achieve