Skip to main content

maxheap

A max-heap library with an API that mirrors Python’s heapq—but max-first. It ships with a fast C accelerator (maxheap._cmaxheap) and a pure-Python fallback.

  • Python: 3.9–3.13
  • License: MIT
  • Package name: maxheap

Features

  • Functional API: heapify, heappush, heappop, heappushpop, heapreplace, peek, is_heap
  • OO wrapper: MaxHeap with push/pop/peek/replace/pushpop
  • Optional C extension for speed; pure-Python fallback if unavailable
  • Reproducible microbenchmarks with CSV output
  • Test suite (pytest) including property tests

Quickstart (from a fresh clone)

Run all commands from the project root (the folder that contains pyproject.toml).

macOS/Linux (bash/zsh)

# 0) Verify you're in the repo root
pwd
ls pyproject.toml

# 1) Create a clean virtualenv
python3 -m venv .venv

# 2) Activate it
source .venv/bin/activate

# 3) Confirm it's active & valid
echo "VIRTUAL_ENV=$VIRTUAL_ENV"
test -x .venv/bin/python && echo "venv OK" || echo "venv MISSING"
python -V

# 4) Install in editable mode (builds the C extension)
python -m pip install -U pip setuptools wheel
python -m pip install -e .

# 5) Sanity check the extension is loaded
python - <<'PY'
import maxheap, sys
print("HAVE_CEXT:", getattr(maxheap, "_HAVE_CEXT", None))
print("heapify impl:", maxheap.heapify.__module__)
print("python:", sys.version)
PY

Expected:

HAVE_CEXT: True
heapify impl: maxheap._cmaxheap
python: 3.13.x (...)

If HAVE_CEXT is False, you’re using the pure-Python fallback.

Windows (PowerShell)

# 0) Verify you're in the repo root
Get-ChildItem pyproject.toml

# 1) Create a venv
py -m venv .venv

# 2) Activate
. .\.venv\Scripts\Activate.ps1

# 3) Install (use -m to ensure the venv's Python)
python -m pip install -U pip setuptools wheel
python -m pip install -e .

# 4) Sanity
python - <<'PY'
import maxheap, sys
print("HAVE_CEXT:", getattr(maxheap, "_HAVE_CEXT", None))
print("heapify impl:", maxheap.heapify.__module__)
print("python:", sys.version)
PY

Rebuilding after C changes

Any time you modify src/maxheap/_cmaxheap.c, rebuild:

# inside the activated venv
rm -rf build
python -m pip install -e .

Usage

The API mirrors Python’s built-in heapq — but instead of a min-heap that requires negating keys for max-first behavior, maxheap stores the largest element at index 0 and operates directly without the negation overhead.

You can choose between a functional API (works on plain lists) and an OO wrapper (MaxHeap class).


Functional API

import maxheap as heapq  # same API names as heapq

# Start with an empty list
h = []

# Push elements
heapq.heappush(h, 3)
heapq.heappush(h, 10)
heapq.heappush(h, 5)

# Peek at the largest without removing it
heapq.peek(h)             # -> 10

# Pop the largest
heapq.heappop(h)          # -> 10
heapq.peek(h)             # -> 5

# Replace the largest atomically
heapq.heapreplace(h, 4)   # pops max (5), pushes 4 -> returns 5

# Push an element and pop the largest in a single step
heapq.heappushpop(h, 7)   # pushes 7, pops max -> returns 7

# Turn any list into a valid max-heap in place
data = [1, 8, 3, 2]
heapq.heapify(data)       # data is now a valid max-heap

When to use:

  • You want to use the heapq-style API but without the min-heap + negation hack.
  • You don’t need to subclass or wrap the heap in your own object.

OO wrapper

from maxheap import MaxHeap

# Initialize from iterable
h = MaxHeap([3, 1, 6, 5, 2, 4])

# Push and pop
h.push(10)
h.peek()   # -> 10
h.pop()    # -> 10

# Length and iteration
len(h)     # -> 6
list(h)    # Pops all items in descending order

# Check if a list is a valid max-heap
MaxHeap.is_heap([10, 5, 6, 2])   # True

When to use:

  • You want an object that owns its heap data.
  • You want utility methods (peek, is_heap, iteration) with clean semantics.

Tip: All hot-path operations (heapify, heappush, heappop, heappushpop, heapreplace) are C-accelerated — so you get max-heap behavior faster than heapq with negation.


Running the tests

# ensure venv is active and package is installed
source .venv/bin/activate  # Windows: .venv\Scripts\activate
python -m pip install -e .
python -m pip install -q pytest hypothesis
python -m pytest -q

You should see all tests green (tests/test_maxheap.py, tests/test_properties.py).


Benchmarks

The benchmark compares maxheap with a baseline using stdlib heapq as a max-heap via negation (-x).

Quick run

python benchmarks/bench_maxheap.py

Larger run + CSV output

mkdir -p benchmarks
python benchmarks/bench_maxheap.py --n 100000 --repeat 10 --warmup 3 --seed 1 \
  --csv benchmarks/results.csv
head benchmarks/results.csv

CLI flags

  • --n (default 10000) — number of items
  • --repeat (default 5) — measured iterations per case
  • --warmup (default 1) — warmup runs
  • --seed (default 1337) — RNG seed
  • --csv — write a results CSV

Benchmarks covered

  • heappush
  • heapify
  • heapify+drain (heapify then pop all)
  • heappushpop
  • heapreplace

Interpreting output

Each line prints min / median / mean. When a baseline exists (the negation variant), a % indicates median speedup (positive = faster than baseline).


A/B: Force the pure-Python fallback (optional)

If you want to compare C vs Python on your machine, temporarily let the package respect an env var:

# top of src/maxheap/__init__.py
import os
try:
    if os.getenv("MAXHEAP_PURE"):
        raise ImportError
    from ._cmaxheap import heapify, heappush, heappop, heappushpop, heapreplace  # type: ignore
    _HAVE_CEXT = True
except Exception:
    from ._core import heapify, heappush, heappop, heappushpop, heapreplace
    _HAVE_CEXT = False

Then:

python -m pip install -e .
python benchmarks/bench_maxheap.py --csv benchmarks/results_cext.csv

MAXHEAP_PURE=1 python benchmarks/bench_maxheap.py --csv benchmarks/results_pure.csv

Packaging (optional)

rm -rf dist
python -m build            # pip install build, if needed
python -m pip install -U twine
twine upload --repository testpypi dist/*

Fresh-venv verification:

python -m venv /tmp/venv && source /tmp/venv/bin/activate
python -m pip install -i https://test.pypi.org/simple/ maxheap
python - <<'PY'
import maxheap
print(maxheap._HAVE_CEXT, maxheap.heapify.__module__)
PY

Project layout

.
├── benchmarks/
│   └── bench_maxheap.py     # microbenchmarks (CSV capable)
├── src/
│   └── maxheap/
│       ├── _cmaxheap.c      # C accelerator (optional)
│       ├── _core.py         # pure-Python implementation
│       └── __init__.py      # optional import of C ext, fallback to Python
├── tests/
│   ├── test_maxheap.py      # unit tests
│   └── test_properties.py   # property-based tests
├── pyproject.toml
└── README.md

Troubleshooting

“.venv/bin/python: No such file or directory” or prompt shows (.venv) but it’s broken

You’re in a shell with a stale venv path. Fix:

deactivate 2>/dev/null || true
rm -rf .venv build *.egg-info src/*.egg-info
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -U pip setuptools wheel
python -m pip install -e .

Check:

echo "$VIRTUAL_ENV"           # should point to .../maxheap/library/.venv
which python                  # should be .../maxheap/library/.venv/bin/python

“ModuleNotFoundError: No module named 'maxheap'”

  • Ensure you ran python -m pip install -e . in the repo root.

  • Ensure tests are run with the same venv:

    python -m pytest -q
    
  • Confirm where maxheap is imported from:

    python - <<'PY'
    

import maxheap, os print(os.path.dirname(maxheap.file)) PY


### Rebuild didn’t pick up code changes

Remove build artifacts and reinstall:

```bash
rm -rf build
python -m pip install -e .

API reference (quick)

# functional API
heapify(x: List[T]) -> None
heappush(heap: List[T], item: T) -> None
heappop(heap: List[T]) -> T
heappushpop(heap: List[T], item: T) -> T
heapreplace(heap: List[T], item: T) -> T
peek(heap: List[T]) -> T
is_heap(x: List[T]) -> bool

# OO wrapper
class MaxHeap(Generic[T]):
    def __init__(self, iterable: Optional[Iterable[T]] = None) -> None: ...
    def push(self, item: T) -> None: ...
    def pop(self) -> T: ...
    def peek(self) -> T: ...
    def replace(self, item: T) -> T: ...
    def pushpop(self, item: T) -> T: ...
    def heap(self) -> List[T]: ...
    def __len__(self) -> int: ...

Notes on performance

  • The accelerator focuses on the hot operations that do comparisons and pointer moves (heapify, heappush, heappop, heappushpop, heapreplace).
  • peek, is_heap, and the MaxHeap wrapper remain in Python—these aren’t hot in typical workloads, and keeping them in Python preserves readability.

Benchmark highlights

operation median time (s) speedup vs heapq+negation
heappush (maxheap) 0.00535 ~19% faster
heapify (maxheap) 0.00349 ~28% faster
heapify+drain (maxheap) 0.04043 ~41% faster

Result: Max-first heap without the negation hack, and still beating the pants off heapq.


Contributing

  • Format/lint: ruff (see pyproject.toml)
  • Types: mypy (strict options)
  • Tests: pytest, property tests via hypothesis

PRs and issues welcome!

Metadata

Release files for maxheapx 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for maxheapx 0.1.1
File
maxheapx-0.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl CPython 3.14 CPython 3.14 free-threading Linux musl 1.2+ x86-64 Details
maxheapx-0.1.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl CPython 3.14 CPython 3.14 free-threading Linux glibc 2.5+ x86-64, Linux glibc 2.28+ x86-64 Details
maxheapx-0.1.1-cp314-cp314-musllinux_1_2_x86_64.whl CPython 3.14 CPython 3.14 Linux musl 1.2+ x86-64 Details
maxheapx-0.1.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.28+ x86-64, Linux glibc 2.5+ x86-64 Details
maxheapx-0.1.1-cp313-cp313-musllinux_1_2_x86_64.whl CPython 3.13 CPython 3.13 Linux musl 1.2+ x86-64 Details
maxheapx-0.1.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.5+ x86-64, Linux glibc 2.28+ x86-64 Details
maxheapx-0.1.1-cp312-cp312-musllinux_1_2_x86_64.whl CPython 3.12 CPython 3.12 Linux musl 1.2+ x86-64 Details
maxheapx-0.1.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64, Linux glibc 2.5+ x86-64 Details
maxheapx-0.1.1-cp311-cp311-musllinux_1_2_x86_64.whl CPython 3.11 CPython 3.11 Linux musl 1.2+ x86-64 Details
maxheapx-0.1.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.5+ x86-64, Linux glibc 2.28+ x86-64 Details
maxheapx-0.1.1-cp310-cp310-musllinux_1_2_x86_64.whl CPython 3.10 CPython 3.10 Linux musl 1.2+ x86-64 Details
maxheapx-0.1.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.28+ x86-64, Linux glibc 2.5+ x86-64 Details
maxheapx-0.1.1-cp39-cp39-musllinux_1_2_x86_64.whl CPython 3.9 CPython 3.9 Linux musl 1.2+ x86-64 Details
maxheapx-0.1.1-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl CPython 3.9 CPython 3.9 Linux glibc 2.5+ x86-64, Linux glibc 2.28+ x86-64 Details

Total release size: 359.5 kB

Release files / maxheapx-0.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl

Download URL maxheapx-0.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl
Size 30.4 kB
Tags CPython 3.14 CPython 3.14 free-threading Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
de606dcdadb9898659b136e9d48f3b272b7a357ddc504486e6c5b77845f97548
BLAKE2b-256 checksum
How to use checksums
8c0e0f719fb5bf642400f7dbdf26753de94ca5c3d46ad039b163346fb9237e75
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl

Download URL maxheapx-0.1.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Size 30.9 kB
Tags CPython 3.14 CPython 3.14 free-threading Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
ff9ea72f8af2a17319892c9c81e560339e4a6bb1b4dc14ea021e657074b508ce
BLAKE2b-256 checksum
How to use checksums
2bb975449ede9353cf5bdde5655a82203eece4d5cbd7c48355df8a11a35d2b3c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp314-cp314-musllinux_1_2_x86_64.whl

Download URL maxheapx-0.1.1-cp314-cp314-musllinux_1_2_x86_64.whl
Size 25.9 kB
Tags CPython 3.14 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
be3f89d05944cece18175c9db639ee519fc1e8c252561e3c92c0835c81ac2e56
BLAKE2b-256 checksum
How to use checksums
f26bc1135414b06712f35844c23daab161b6fc89ad3b8df41f4396b4ba2bc22b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl

Download URL maxheapx-0.1.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Size 26.1 kB
Tags CPython 3.14 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
abd549dd40421a037bc89c784e6402517c4010f89018252b0dc50522fb8cfe36
BLAKE2b-256 checksum
How to use checksums
7ea02b5c4e15e164e6c496561aaa0663854e5174f67af9cee7ea3730f31165fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp313-cp313-musllinux_1_2_x86_64.whl

Download URL maxheapx-0.1.1-cp313-cp313-musllinux_1_2_x86_64.whl
Size 25.8 kB
Tags CPython 3.13 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
5fa895db83d63bdd56aae86130254f47a83ac235837474082f819b036ee23efe
BLAKE2b-256 checksum
How to use checksums
53f32a610a5b504b1c8c6b8ea5fa85319063cb659a7d34286cab331474b9084d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl

Download URL maxheapx-0.1.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Size 26.0 kB
Tags CPython 3.13 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
c909e1492f0f8616d0c753ce519542c43ef46e2204bd95f14c650fabc4838439
BLAKE2b-256 checksum
How to use checksums
6b6028d187c6e7cdfbc747a62e857f31cab6681ce0194a906f784fa5b1f9dc9d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp312-cp312-musllinux_1_2_x86_64.whl

Download URL maxheapx-0.1.1-cp312-cp312-musllinux_1_2_x86_64.whl
Size 25.8 kB
Tags CPython 3.12 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
742c4acfb592f9164ca7f4cc780fbe67ed1ca704ee81ca94172de06eb4a73326
BLAKE2b-256 checksum
How to use checksums
c712a0d96d3290529c49b77d093d35e305ecf94c4b8d1e397798f950957ecbf5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl

Download URL maxheapx-0.1.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Size 25.9 kB
Tags CPython 3.12 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
80df0a07193729b9134c04bac958ce7d96a857422ff38821a5a154a1bf9c5ee2
BLAKE2b-256 checksum
How to use checksums
9c840828b5109013d052e3b716b00392f01b8c8cc4647f5d5f4d1ad4dfaa59f8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp311-cp311-musllinux_1_2_x86_64.whl

Download URL maxheapx-0.1.1-cp311-cp311-musllinux_1_2_x86_64.whl
Size 24.8 kB
Tags CPython 3.11 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
5c2ab61f5749e96a6566fd644aebd0308faef440948efb7b9af3c605dd58788b
BLAKE2b-256 checksum
How to use checksums
a092f6dd0eb50f49e0a73cad8756b15aabbc9161b328856d4a31dcac47f7ee91
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl

Download URL maxheapx-0.1.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Size 24.8 kB
Tags CPython 3.11 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
574863a484f24d78f7b543de8f50978d99a6f92788261aac9c3a36d2a56c4906
BLAKE2b-256 checksum
How to use checksums
4c93355b59881e6307e214cbeccf73531ebb0c0b8fe593f614ad1bb92d8c71dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp310-cp310-musllinux_1_2_x86_64.whl

Download URL maxheapx-0.1.1-cp310-cp310-musllinux_1_2_x86_64.whl
Size 23.4 kB
Tags CPython 3.10 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
476f66e0432e6fb45661a57b22652188c3682506628e79e5227cbd17f98cc6f5
BLAKE2b-256 checksum
How to use checksums
324bec30a01bc100e119fac77649ec34927a7966891e8fecd68ff75afc6969be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl

Download URL maxheapx-0.1.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Size 23.4 kB
Tags CPython 3.10 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
353c19a43c4ba07b9ca88a66d3f792fac82ab91423a1c840e3e53dbf12a00b6b
BLAKE2b-256 checksum
How to use checksums
9b14bd8319b78da282e65bc401996465d69cc9f2d58821fa7627f5f08e921d90
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp39-cp39-musllinux_1_2_x86_64.whl

Download URL maxheapx-0.1.1-cp39-cp39-musllinux_1_2_x86_64.whl
Size 23.2 kB
Tags CPython 3.9 Linux musl 1.2+ x86-64
SHA-256 checksum
How to use checksums
70d3d323edbd8765e50642f035ca5670a16e899c105a77f402ff2e6435c484d0
BLAKE2b-256 checksum
How to use checksums
785b72094cc5a5aba564c508da1904be28de124c70e634928cf1bcf6f73d0709
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / maxheapx-0.1.1-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl

Download URL maxheapx-0.1.1-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Size 23.2 kB
Tags CPython 3.9 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64
SHA-256 checksum
How to use checksums
bab208c6a6cb26c61220afc6ee013391d325a362d307218f7ab9f18d285bc69a
BLAKE2b-256 checksum
How to use checksums
c3b12a7f8496a80578b9c6df20127eaa169552310b14bc6b3379fa2ceb6af3c3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release history Release notifications | RSS feed

This release

0.1.1 This release

14 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page