We’ve learned about Queues, and discovered that queues are processed First In, First Out (FIFO). Essentially, this means:
- Data is inserted only at the end
- Data is removed at the front
- Data is only accessed at the front
A priority queue is an abstract data type similar to a regular queue or stack data structure in which each eleemnt additionally has a “priority” associated with it. In a priority queue, an element with high priority is served before an element with low priority.
Wikipedia
A common myth is that a Heap is the same as a priority queue. A priority queue is an abstract data type, while a Heap is a data structure. An abstract data type is derived from (or simply “built on”) data structures. Therefore, a heap is not a priority queue, but a way to implement one.
In theory it is possible to build a priority queue from an array or list, but these implementations only guarantee O(1) for insertion or deletion. While implementing a priority queue with a heap give us the best of both worlds: O(log N) insertion, deletion, and search. Because people most often build a priority queue from a heap, both priority queue and heap are used interchangeably.
Using A Priority Queue
var priorityQueue = new PriorityQueue<int>();
// Enqueue elements with priorities
priorityQueue.Enqueue(3, 3);
priorityQueue.Enqueue(1, 1);
priorityQueue.Enqueue(2, 2);
// Peek at the element with highest priority
int peekedValue = priorityQueue.Peek();
Console.WriteLine("Peeked Value: " + peekedValue); // Outputs "1"
// Dequeue elements in priority order
while (priorityQueue.Count > 0)
{
int dequeuedValue = priorityQueue.Dequeue();
Console.WriteLine("Dequeued Value: " + dequeuedValue);
}
Practical Use Case
Another practical use case for a PriorityQueue in C# involves event scheduling. Let’s explore an example where a priority queue can be used to manage tasks with varying priorities effectively.
- Define a Task
public enum Priority
{
Low,
Medium,
High
}
public class Task
{
public string Description { get; set; }
public Priority Priority { get; set; }
public Task(string description, Priority priority)
{
Description = description;
Priority = priority;
}
}
2. Setup a Priority Queue
public class TaskManager
{
private PriorityQueue<Task, Priority> taskQueue = new PriorityQueue<Task, Priority>();
public void AddTask(string description, Priority priority)
{
var task = new Task(description, priority);
taskQueue.Enqueue(task, priority);
}
public Task GetNextTask()
{
if (taskQueue.Count > 0)
{
return taskQueue.Dequeue().Item1;
}
else
{
return null;
}
}
}
3. Usage Example
TaskManager taskManager = new TaskManager();
// Adding tasks with different priorities
taskManager.AddTask("Implement feature X", Priority.High);
taskManager.AddTask("Fix bug in module Y", Priority.Medium);
taskManager.AddTask("Refactor class Z", Priority.Low);
// Processing tasks in priority order
Task nextTask;
while ((nextTask = taskManager.GetNextTask()) != null)
{
Console.WriteLine($"Processing task: {nextTask.Description} (Priority: {nextTask.Priority})");
// Simulate task processing...
}
A PriorityQueue
in C# manages based on priority, providing optimal performance in scenarios requiring prioritized access. When prioritization and efficient handling of elements are crucial, opting for a PriorityQueue
is often the better choice in C#.