ZetCode

Dart HeapPriorityQueue

last modified April 4, 2025

In Dart, HeapPriorityQueue is an implementation of a priority queue based on a heap data structure. It maintains elements in order according to their priority.

Elements are ordered either by their natural ordering or by a comparator function. The highest priority element is always at the front of the queue.

Creating a HeapPriorityQueue

The simplest way to create a HeapPriorityQueue is using the constructor with a comparator function.

main.dart
import 'dart:collection';

void main() {
  var pq = HeapPriorityQueue<int>((a, b) => a.compareTo(b));
  pq.add(5);
  pq.add(3);
  pq.add(7);
  pq.add(1);

  print(pq.removeFirst()); // 1 (highest priority)
  print(pq.removeFirst()); // 3
}

We create a min-heap priority queue that orders integers in ascending order. The comparator function defines the priority order. removeFirst always returns the highest priority element.

$ dart main.dart
1
3

Custom Comparator for Objects

We can use custom objects with a comparator function to define priority.

main.dart
import 'dart:collection';

class Task {
  final String name;
  final int priority;

  Task(this.name, this.priority);

  @override
  String toString() => '$name ($priority)';
}

void main() {
  var taskQueue = HeapPriorityQueue<Task>(
    (a, b) => b.priority.compareTo(a.priority) // Max-heap
  );

  taskQueue.add(Task('Write report', 2));
  taskQueue.add(Task('Fix bug', 5));
  taskQueue.add(Task('Test feature', 3));

  while (taskQueue.isNotEmpty) {
    print(taskQueue.removeFirst());
  }
}

We create a max-heap priority queue for Task objects. Higher priority numbers come first. The comparator reverses the comparison to create a max-heap.

$ dart main.dart
Fix bug (5)
Test feature (3)
Write report (2)

Basic Operations

HeapPriorityQueue provides essential queue operations like add, remove, and peek.

main.dart
import 'dart:collection';

void main() {
  var pq = HeapPriorityQueue<int>((a, b) => a.compareTo(b));
  
  // Add elements
  pq.add(10);
  pq.addAll([5, 15, 3]);
  
  // Check properties
  print('Length: ${pq.length}');
  print('First element: ${pq.first}');
  print('Is empty: ${pq.isEmpty}');
  
  // Remove elements
  print('Removed: ${pq.removeFirst()}');
  print('Removed: ${pq.removeFirst()}');
}

This demonstrates basic operations. addAll adds multiple elements. first peeks at the highest priority element without removing it. removeFirst removes and returns it.

$ dart main.dart
Length: 4
First element: 3
Is empty: false
Removed: 3
Removed: 5

Handling Duplicates

HeapPriorityQueue can handle duplicate elements while maintaining order.

main.dart
import 'dart:collection';

void main() {
  var pq = HeapPriorityQueue<int>((a, b) => a.compareTo(b));
  pq.addAll([5, 3, 5, 7, 3, 1]);

  print('All elements:');
  while (pq.isNotEmpty) {
    print(pq.removeFirst());
  }

  print('\nContains 5: ${pq.contains(5)}');
  pq.add(5);
  print('Contains 5 after add: ${pq.contains(5)}');
}

Duplicate values are allowed in the priority queue. The contains method checks for element presence. The queue maintains order even with duplicates.

$ dart main.dart
All elements:
1
3
3
5
5
7

Contains 5: false
Contains 5 after add: true

Priority Queue with Custom Ordering

We can implement complex ordering logic with custom comparators.

main.dart
import 'dart:collection';

class Student {
  final String name;
  final double gpa;
  final int credits;

  Student(this.name, this.gpa, this.credits);

  @override
  String toString() => '$name (GPA: $gpa, Credits: $credits)';
}

void main() {
  var studentQueue = HeapPriorityQueue<Student>((a, b) {
    // Primary sort by GPA (descending), secondary by credits (ascending)
    var gpaCompare = b.gpa.compareTo(a.gpa);
    if (gpaCompare != 0) return gpaCompare;
    return a.credits.compareTo(b.credits);
  });

  studentQueue.add(Student('Alice', 3.7, 90));
  studentQueue.add(Student('Bob', 3.9, 85));
  studentQueue.add(Student('Charlie', 3.7, 95));
  studentQueue.add(Student('David', 3.5, 100));

  print('Students in priority order:');
  while (studentQueue.isNotEmpty) {
    print(studentQueue.removeFirst());
  }
}

We implement a multi-level comparator that first sorts by GPA (descending) then by credits (ascending). This shows the flexibility of HeapPriorityQueue ordering.

$ dart main.dart
Students in priority order:
Bob (GPA: 3.9, Credits: 85)
Alice (GPA: 3.7, Credits: 90)
Charlie (GPA: 3.7, Credits: 95)
David (GPA: 3.5, Credits: 100)

Best Practices

Source

Dart HeapPriorityQueue Documentation

This tutorial covered Dart's HeapPriorityQueue with practical examples demonstrating its key features and usage patterns for priority-based processing.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Dart tutorials.