// MIT License - Copyright (c) 2025 wallstop
// Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE
namespace WallstopStudios.UnityHelpers.Core.DataStructure
{
using System;
using System.Collections;
using System.Collections.Generic;
///
/// A priority queue implemented as a thin wrapper around .
/// Provides clearer semantics for priority-based task scheduling, A* pathfinding,
/// event systems, and AI decision making. Supports both min-priority and max-priority modes.
///
///
/// open = new PriorityQueue(Comparer.Create((a, b) => a.F.CompareTo(b.F)));
/// open.Enqueue(startNode);
/// while (!open.IsEmpty && open.TryDequeue(out PathNode current))
/// {
/// // process node
/// }
/// ]]>
///
[Serializable]
public sealed class PriorityQueue : IEnumerable
{
private readonly Heap _heap;
///
/// Gets the number of elements in the priority queue.
///
public int Count => _heap.Count;
///
/// Gets whether the priority queue is empty.
///
public bool IsEmpty => _heap.IsEmpty;
///
/// Gets the current capacity of the underlying heap.
///
public int Capacity => _heap.Capacity;
public PriorityQueue()
: this(16) { }
///
/// Constructs a priority queue with the default comparer (min-priority).
///
public PriorityQueue(int capacity)
: this(Comparer.Default, capacity) { }
///
/// Constructs a priority queue with a custom comparer.
///
public PriorityQueue(IComparer comparer, int capacity = 16)
{
_heap = new Heap(comparer, capacity);
}
///
/// Constructs a priority queue from an existing collection.
///
public PriorityQueue(IEnumerable items, IComparer comparer = null)
{
_heap = new Heap(items, comparer);
}
///
/// Creates a min-priority queue (lowest priority dequeued first).
///
public static PriorityQueue CreateMin(int capacity = 16)
{
return new PriorityQueue(Comparer.Default, capacity);
}
///
/// Creates a max-priority queue (highest priority dequeued first).
///
public static PriorityQueue CreateMax(int capacity = 16)
{
return new PriorityQueue(
Comparer.Create((x, y) => Comparer.Default.Compare(y, x)),
capacity
);
}
///
/// Creates a min-priority queue from an existing collection.
///
public static PriorityQueue CreateMin(IEnumerable items)
{
return new PriorityQueue(items, Comparer.Default);
}
///
/// Creates a max-priority queue from an existing collection.
///
public static PriorityQueue CreateMax(IEnumerable items)
{
return new PriorityQueue(
items,
Comparer.Create((x, y) => Comparer.Default.Compare(y, x))
);
}
///
/// Enqueues an element with its priority in O(log n) time.
///
public void Enqueue(T item)
{
_heap.Add(item);
}
///
/// Attempts to dequeue the highest priority element in O(log n) time.
///
public bool TryDequeue(out T result)
{
return _heap.TryPop(out result);
}
///
/// Attempts to peek at the highest priority element without removing it.
///
public bool TryPeek(out T result)
{
return _heap.TryPeek(out result);
}
///
/// Removes all elements from the priority queue.
///
public void Clear()
{
_heap.Clear();
}
///
/// Checks if the priority queue contains a specific element in O(n) time.
///
public bool Contains(T item)
{
return _heap.Contains(item);
}
///
/// Attempts to update the priority of an element at the specified index.
/// The index refers to internal heap storage order, not priority order.
/// Returns false if index is invalid.
///
public bool TryUpdatePriority(int index, T newValue)
{
return _heap.TryUpdatePriority(index, newValue);
}
///
/// Attempts to get the element at the specified internal index.
/// The index refers to internal heap storage order, not priority order.
///
public bool TryGet(int index, out T result)
{
return _heap.TryGet(index, out result);
}
///
/// Returns an array containing all elements (not in priority order).
///
public T[] ToArray()
{
return _heap.ToArray();
}
public int ToArray(ref T[] result)
{
return _heap.ToArray(ref result);
}
///
/// Trims excess capacity to match the current count.
///
public void TrimExcess()
{
_heap.TrimExcess();
}
///
/// Returns an enumerator that iterates through all elements in internal heap order (not priority order).
/// Note: Iteration order is NOT sorted by priority. Use DequeueAll for priority-sorted iteration.
///
public Heap.HeapEnumerator GetEnumerator()
{
return _heap.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}