Home

Priority Queue


A priority queue is an abstract data type where each item has an associated priority.

A priority queue supports the following main operations:

Priority Queue Implementations


Unordered array:

Ordered array:

Unordered linked list:

Ordered linked list:

Heaps


A heap is a tree-based data structure which satisfies the heap property.

The heap property specifies how values in the heap should be ordered, and depends on the kind of heap:

In a max heap, the value in each node must be greater than or equal to the values in its children.

In a min heap, the value in each node must be less than or equal to the values in its children.

A binary heap is a heap that takes the form of a binary tree, and satisfies the following properties:

A result of the completeness property is that binary heaps always contain $\lfloor \log_2 n \rfloor + 1$ levels where $n$ is the number of nodes.

Heaps are usually implemented with an array.

For a binary heap, index 1 of the array contains the root item, the next two indices contain the root’s children, the next four indices contain the children of the root’s children, and so on.

heap

For an item at index $i$:

Note: the following operations focuses on max heaps

Binary Heap Insertion


Insertion is a two-step process:

  1. Add new item at next available position on bottom level (i.e., after the last item)
  1. Fix up: While new item is greater than its parent (and not at the root), swap with its parent

Cost of insertion:

Binary Heap Deletion


Deletion is a three-step process:

  1. Replace root item with last item
  1. Remove last item
  2. Fix down: While $i$ is less than its greater child, swap it with its greater child

Cost of deletion:

Using Heaps for Priority Queues


Now that we have learned heaps, we can use it to implement a more efficient priority queue.

Heap Sort


Heap sort is a sorting algorithm that uses a heap

Method:

Heapify (Fix Up)


void heapify(Item items[], int size) {
  for (int i = 1; i < size; i++) {
    fixUp(items, i);
  }
}

void fixUp(Item items[], int i) {
  while (i > 0 && items[i] > items[(i - 1) / 2]) {
    swap(items, i, (i - 1) / 2);
    i = (i - 1) / 2;
  }
}

Analysis:

Heapify (Fix Down)


Heapify can be implemented more efficiently by performing a fix down on every element in the first half of the array in reverse (i.e., from right to left)

Examples are in the lecture slides.

void heapify(Item items[], int size) {
  for (int i = size / 2 - 1; i >= 0; i--) {
    fixDown(items, i, size - 1);
  }
}

void fixDown(Item items[], int i, int N) {
  while (2 * i + 1 <= N) {
    int j = 2 * i + 1;
    if (j < N && items[j] < items[j + 1]) j++;
    if (items[i] >= items[j]) break;
    swap(items, i, j);
    i = j;
  }
}

This implementation of heapify is O(n).

De-Heapify


After the array has been heapified, repeatedly delete from the heap, each time placing the deleted item at the end of the heap.

void deheapify(Item items[], int size) {
  while (size > 1) {
    swap(items, 0, size - 1);
    size--;
    fixDown(items, 0, size - 1);
  }
}

Analysis:

Analysis of Heap Sort


Properties:

Unstable: Due to long-range swaps
Non-adaptive: $O(n \log n)$ average case and if array is sorted
In-place: Sorting is done within original array; does not use temporary arrays