← Back

Binary Heap (Priority Queue)

A min-heap on a slice: O(log n) push and pop via sift-up and sift-down.

1 / 1
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

func (h *MinHeap) Push(x int) {
    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
    h.data = append(h.data, x)
}
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

func (h *MinHeap) Push(x int) {
    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
    h.data = append(h.data, x)

    // Bubble the newcomer up until it's >= its parent again.
}
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

func (h *MinHeap) Push(x int) {
    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
    h.data = append(h.data, x)

    // Bubble the newcomer up until it's >= its parent again.
    h.up(len(h.data) - 1)
}
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

func (h *MinHeap) Push(x int) {
    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
    h.data = append(h.data, x)

    // Bubble the newcomer up until it's >= its parent again.
    h.up(len(h.data) - 1)
}

    // The min lives at the root. Swap it with the last leaf so we can remove it
    // from the end cheaply.
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

func (h *MinHeap) Push(x int) {
    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
    h.data = append(h.data, x)

    // Bubble the newcomer up until it's >= its parent again.
    h.up(len(h.data) - 1)
}

func (h *MinHeap) Pop() int {
    // The min lives at the root. Swap it with the last leaf so we can remove it
    // from the end cheaply.
    n := len(h.data) - 1
    h.data[0], h.data[n] = h.data[n], h.data[0]
    min := h.data[n]
}
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

func (h *MinHeap) Push(x int) {
    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
    h.data = append(h.data, x)

    // Bubble the newcomer up until it's >= its parent again.
    h.up(len(h.data) - 1)
}

func (h *MinHeap) Pop() int {
    // The min lives at the root. Swap it with the last leaf so we can remove it
    // from the end cheaply.
    n := len(h.data) - 1
    h.data[0], h.data[n] = h.data[n], h.data[0]
    min := h.data[n]

    // Drop the old min, then sift the leaf that's now at the root back down.
}
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

func (h *MinHeap) Push(x int) {
    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
    h.data = append(h.data, x)

    // Bubble the newcomer up until it's >= its parent again.
    h.up(len(h.data) - 1)
}

func (h *MinHeap) Pop() int {
    // The min lives at the root. Swap it with the last leaf so we can remove it
    // from the end cheaply.
    n := len(h.data) - 1
    h.data[0], h.data[n] = h.data[n], h.data[0]
    min := h.data[n]

    // Drop the old min, then sift the leaf that's now at the root back down.
    h.data = h.data[:n]
    h.down(0)
    return min
}
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

func (h *MinHeap) Push(x int) {
    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
    h.data = append(h.data, x)

    // Bubble the newcomer up until it's >= its parent again.
    h.up(len(h.data) - 1)
}

func (h *MinHeap) Pop() int {
    // The min lives at the root. Swap it with the last leaf so we can remove it
    // from the end cheaply.
    n := len(h.data) - 1
    h.data[0], h.data[n] = h.data[n], h.data[0]
    min := h.data[n]

    // Drop the old min, then sift the leaf that's now at the root back down.
    h.data = h.data[:n]
    h.down(0)
    return min
}

// up: while a node is smaller than its parent, swap them and follow it upward.
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

func (h *MinHeap) Push(x int) {
    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
    h.data = append(h.data, x)

    // Bubble the newcomer up until it's >= its parent again.
    h.up(len(h.data) - 1)
}

func (h *MinHeap) Pop() int {
    // The min lives at the root. Swap it with the last leaf so we can remove it
    // from the end cheaply.
    n := len(h.data) - 1
    h.data[0], h.data[n] = h.data[n], h.data[0]
    min := h.data[n]

    // Drop the old min, then sift the leaf that's now at the root back down.
    h.data = h.data[:n]
    h.down(0)
    return min
}

// up: while a node is smaller than its parent, swap them and follow it upward.
func (h *MinHeap) up(i int) {
    for i > 0 {
        parent := (i - 1) / 2
        if h.data[parent] <= h.data[i] {
            break // parent already <= node: invariant restored
        }
        h.data[parent], h.data[i] = h.data[i], h.data[parent]
        i = parent
    }
}
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

func (h *MinHeap) Push(x int) {
    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
    h.data = append(h.data, x)

    // Bubble the newcomer up until it's >= its parent again.
    h.up(len(h.data) - 1)
}

func (h *MinHeap) Pop() int {
    // The min lives at the root. Swap it with the last leaf so we can remove it
    // from the end cheaply.
    n := len(h.data) - 1
    h.data[0], h.data[n] = h.data[n], h.data[0]
    min := h.data[n]

    // Drop the old min, then sift the leaf that's now at the root back down.
    h.data = h.data[:n]
    h.down(0)
    return min
}

// up: while a node is smaller than its parent, swap them and follow it upward.
func (h *MinHeap) up(i int) {
    for i > 0 {
        parent := (i - 1) / 2
        if h.data[parent] <= h.data[i] {
            break // parent already <= node: invariant restored
        }
        h.data[parent], h.data[i] = h.data[i], h.data[parent]
        i = parent
    }
}

// down: repeatedly swap a node with its SMALLEST child until it sits above both.
        // Assume i is smallest, then check its two children.
// A binary heap is stored in a flat slice. For the node at index i:
//   left child  = 2i+1, right child = 2i+2, parent = (i-1)/2.
// The heap invariant: every parent is <= its children, so the min is at index 0.
type MinHeap struct {
    data []int
}

func (h *MinHeap) Push(x int) {
    // Append at the end — that keeps the tree "complete", but may break the
    // invariant, since the new leaf could be smaller than its parent.
    h.data = append(h.data, x)

    // Bubble the newcomer up until it's >= its parent again.
    h.up(len(h.data) - 1)
}

func (h *MinHeap) Pop() int {
    // The min lives at the root. Swap it with the last leaf so we can remove it
    // from the end cheaply.
    n := len(h.data) - 1
    h.data[0], h.data[n] = h.data[n], h.data[0]
    min := h.data[n]

    // Drop the old min, then sift the leaf that's now at the root back down.
    h.data = h.data[:n]
    h.down(0)
    return min
}

// up: while a node is smaller than its parent, swap them and follow it upward.
func (h *MinHeap) up(i int) {
    for i > 0 {
        parent := (i - 1) / 2
        if h.data[parent] <= h.data[i] {
            break // parent already <= node: invariant restored
        }
        h.data[parent], h.data[i] = h.data[i], h.data[parent]
        i = parent
    }
}

// down: repeatedly swap a node with its SMALLEST child until it sits above both.
func (h *MinHeap) down(i int) {
    n := len(h.data)
    for {
        // Assume i is smallest, then check its two children.
        smallest, l, r := i, 2*i+1, 2*i+2
        if l < n && h.data[l] < h.data[smallest] {
            smallest = l
        }
        if r < n && h.data[r] < h.data[smallest] {
            smallest = r
        }
        if smallest == i {
            break // node is already <= both children
        }
        h.data[i], h.data[smallest] = h.data[smallest], h.data[i]
        i = smallest
    }
}

Tap the left half to go back, the right half to go forward.

Arrow keys or space to navigate · Esc to exit.