From e6553877ebd7c95f62347823f9d6ba84e892b8b1 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Tue, 9 Mar 2021 21:58:55 +0000 Subject: [PATCH] improve PriorityQueue documentation --- .../Collections/Generic/PriorityQueue.cs | 159 ++++++++++++++---- 1 file changed, 125 insertions(+), 34 deletions(-) diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs index 554f7f0e84c40..5918bc1a62915 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs @@ -8,11 +8,14 @@ namespace System.Collections.Generic { /// - /// Represents a data structure in which each element has an associated priority - /// that determines the order in which the pair is dequeued. + /// Represents a min priority queue. /// - /// The type of the element. - /// The type of the priority. + /// Specifies the type of elements in the queue. + /// Specifies the type of priority associated with enqueued elements. + /// + /// Implements an array-backed quaternary min-heap. Each element is enqueued with an associated priority + /// that determines the dequeue order: elements with the lowest priority get dequeued first. + /// [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(PriorityQueueDebugView<,>))] public class PriorityQueue @@ -61,7 +64,7 @@ static PriorityQueue() #endif /// - /// Creates an empty priority queue. + /// Initializes a new instance of the class. /// public PriorityQueue() { @@ -70,16 +73,26 @@ public PriorityQueue() } /// - /// Creates an empty priority queue with the specified initial capacity for its underlying array. + /// Initializes a new instance of the class + /// with the specified initial capacity. /// + /// Initial capacity to allocate in the underlying heap array. + /// + /// The specified was negative. + /// public PriorityQueue(int initialCapacity) : this(initialCapacity, comparer: null) { } /// - /// Creates an empty priority queue with the specified priority comparer. + /// Initializes a new instance of the class + /// with the specified custom priority comparer. /// + /// + /// Custom comparer dictating the ordering of elements. + /// Uses if the argument is . + /// public PriorityQueue(IComparer? comparer) { _nodes = Array.Empty<(TElement, TPriority)>(); @@ -87,9 +100,17 @@ public PriorityQueue(IComparer? comparer) } /// - /// Creates an empty priority queue with the specified priority comparer and - /// the specified initial capacity for its underlying array. + /// Initializes a new instance of the class + /// with the specified initial capacity and custom priority comparer. /// + /// Initial capacity to allocate in the underlying heap array. + /// + /// Custom comparer dictating the ordering of elements. + /// Uses if the argument is . + /// + /// + /// The specified was negative. + /// public PriorityQueue(int initialCapacity, IComparer? comparer) { if (initialCapacity < 0) @@ -103,17 +124,39 @@ public PriorityQueue(int initialCapacity, IComparer? comparer) } /// - /// Creates a priority queue populated with the specified elements and priorities. + /// Initializes a new instance of the class + /// that is populated with the specified elements and priorities. /// + /// The pairs of elements and priorities with which to populate the queue. + /// + /// The specified argument was . + /// + /// + /// Constructs the heap using a heapify operation, + /// which is generally faster than enqueuing individual elements sequentially. + /// public PriorityQueue(IEnumerable<(TElement Element, TPriority Priority)> items) : this(items, comparer: null) { } /// - /// Creates a priority queue populated with the specified elements and priorities, - /// and with the specified priority comparer. - /// + /// Initializes a new instance of the class + /// that is populated with the specified elements and priorities, + /// and with the specified custom priority comparer. + /// + /// The pairs of elements and priorities with which to populate the queue. + /// + /// Custom comparer dictating the ordering of elements. + /// Uses if the argument is . + /// + /// + /// The specified argument was . + /// + /// + /// Constructs the heap using a heapify operation, + /// which is generally faster than enqueuing individual elements sequentially. + /// public PriorityQueue(IEnumerable<(TElement Element, TPriority Priority)> items, IComparer? comparer) { if (items is null) @@ -131,23 +174,29 @@ public PriorityQueue(IEnumerable<(TElement Element, TPriority Priority)> items, } /// - /// Gets the current amount of items in the priority queue. + /// Gets the number of elements contained in the . /// public int Count => _size; /// - /// Gets the priority comparer of the priority queue. + /// Gets the priority comparer used by the . /// public IComparer Comparer => _comparer ?? Comparer.Default; /// - /// Gets a collection that enumerates the elements of the queue. + /// Gets a collection that enumerates the elements of the queue in an unordered manner. /// + /// + /// The enumeration does not order items by priority, since that would require N * log(N) time and N space. + /// Items are instead enumerated following the internal array heap layout. + /// public UnorderedItemsCollection UnorderedItems => _unorderedItems ??= new UnorderedItemsCollection(this); /// - /// Enqueues the specified element and associates it with the specified priority. + /// Adds the specified element with associated priority to the . /// + /// The element to add to the . + /// The priority with which to associate the new element. public void Enqueue(TElement element, TPriority priority) { // Virtually add the node at the end of the underlying array. @@ -173,9 +222,10 @@ public void Enqueue(TElement element, TPriority priority) } /// - /// Gets the element associated with the minimal priority. + /// Returns the minimal element from the without removing it. /// - /// The queue is empty. + /// The is empty. + /// The minimal element of the . public TElement Peek() { if (_size == 0) @@ -187,9 +237,10 @@ public TElement Peek() } /// - /// Dequeues the element associated with the minimal priority. + /// Removes and returns the minimal element from the . /// /// The queue is empty. + /// The minimal element of the . public TElement Dequeue() { if (_size == 0) @@ -203,10 +254,15 @@ public TElement Dequeue() } /// - /// Dequeues the element associated with the minimal priority + /// Removes the minimal element from the , + /// and copies it to the parameter, + /// and its associated priority to the parameter. /// + /// The removed element. + /// The priority associated with the removed element. /// - /// if the priority queue is non-empty; otherwise. + /// if the element is successfully removed; + /// if the is empty. /// public bool TryDequeue([MaybeNullWhen(false)] out TElement element, [MaybeNullWhen(false)] out TPriority priority) { @@ -223,10 +279,16 @@ public bool TryDequeue([MaybeNullWhen(false)] out TElement element, [MaybeNullWh } /// - /// Gets the element associated with the minimal priority. + /// Returns a value that indicates whether there is a minimal element in the , + /// and if one is present, copies it to the parameter, + /// and its associated priority to the parameter. + /// The element is not removed from the . /// + /// The minimal element in the queue. + /// The priority associated with the minimal element. /// - /// if the priority queue is non-empty; otherwise. + /// if there is a minimal element; + /// if the is empty. /// public bool TryPeek([MaybeNullWhen(false)] out TElement element, [MaybeNullWhen(false)] out TPriority priority) { @@ -242,8 +304,17 @@ public bool TryPeek([MaybeNullWhen(false)] out TElement element, [MaybeNullWhen( } /// - /// Combined enqueue/dequeue operation, generally more efficient than sequential Enqueue/Dequeue calls. + /// Adds the specified element with associated priority to the , + /// and immediately removes the minimal element, returning the result. /// + /// The element to add to the . + /// The priority with which to associate the new element. + /// The minimal element removed after the enqueue operation. + /// + /// Implements an insert-then-extract heap operation that is generally more efficient + /// than sequencing Enqueue and Dequeue operations: in the worst case scenario only one + /// sift-down operation is required. + /// public TElement EnqueueDequeue(TElement element, TPriority priority) { if (_size != 0) @@ -274,8 +345,12 @@ public TElement EnqueueDequeue(TElement element, TPriority priority) } /// - /// Enqueues a collection of element/priority pairs. + /// Enqueues a sequence of element/priority pairs to the . /// + /// The pairs of elements and priorities to add to the queue. + /// + /// The specified argument was . + /// public void EnqueueRange(IEnumerable<(TElement Element, TPriority Priority)> items) { if (items is null) @@ -308,8 +383,14 @@ public void EnqueueRange(IEnumerable<(TElement Element, TPriority Priority)> ite } /// - /// Enqueues a collection of elements, each associated with the specified priority. + /// Enqueues a sequence of elements pairs to the , + /// all associated with the specified priority. /// + /// The elements to add to the queue. + /// The priority to associate with the new elements. + /// + /// The specified argument was . + /// public void EnqueueRange(IEnumerable elements, TPriority priority) { if (elements is null) @@ -353,7 +434,7 @@ public void EnqueueRange(IEnumerable elements, TPriority priority) } /// - /// Removes all items from the priority queue. + /// Removes all items from the . /// public void Clear() { @@ -367,9 +448,14 @@ public void Clear() } /// - /// Ensures that the priority queue has the specified capacity - /// and resizes its underlying array if necessary. + /// Ensures that the can hold up to + /// items without further expansion of its backing storage. /// + /// The minimum capacity to be used. + /// + /// The specified is negative. + /// + /// The current capacity of the . public int EnsureCapacity(int capacity) { if (capacity < 0) @@ -387,9 +473,13 @@ public int EnsureCapacity(int capacity) } /// - /// Sets the capacity to the actual number of items in the priority queue, - /// if that is less than 90 percent of current capacity. + /// Sets the capacity to the actual number of items in the , + /// if that is less than 90 percent of current capacity. /// + /// + /// This method can be used to minimize a collection's memory overhead + /// if no new elements will be added to the collection. + /// public void TrimExcess() { int threshold = (int)(_nodes.Length * 0.9); @@ -677,7 +767,7 @@ private void MoveDownCustomComparer((TElement Element, TPriority Priority) node, } /// - /// Represents the contents of a without ordering. + /// Enumerates the contents of a , without any ordering guarantees. /// [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(PriorityQueueDebugView<,>))] @@ -729,7 +819,8 @@ void ICollection.CopyTo(Array array, int index) } /// - /// Enumerates the element and priority pairs of a . + /// Enumerates the element and priority pairs of a , + /// without any ordering guarantees. /// public struct Enumerator : IEnumerator<(TElement Element, TPriority Priority)> {