-
-
Notifications
You must be signed in to change notification settings - Fork 126
Expand file tree
/
Copy pathPriorityQueue.cs
More file actions
115 lines (94 loc) · 3.25 KB
/
PriorityQueue.cs
File metadata and controls
115 lines (94 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#if !NET
using System.Diagnostics.CodeAnalysis;
namespace TUnit.Engine
{
public class PriorityQueue<TElement, TPriority> where TPriority : IComparable<TPriority>
{
private readonly List<Element> _elements = [];
private struct Element(TElement value, TPriority priority)
{
public readonly TElement Value = value;
public readonly TPriority Priority = priority;
}
public int Count => _elements.Count;
public void Enqueue(TElement value, TPriority priority)
{
var element = new Element(value, priority);
_elements.Add(element);
HeapifyUp(_elements.Count - 1);
}
public TElement Dequeue()
{
if (_elements.Count == 0)
{
throw new InvalidOperationException("The priority queue is empty.");
}
var element = _elements[0];
_elements[0] = _elements[^1];
_elements.RemoveAt(_elements.Count - 1);
HeapifyDown(0);
return element.Value;
}
public bool TryDequeue([NotNullWhen(true)] out TElement? value, [NotNullWhen(true)] out TPriority? priority)
{
if (_elements.Count == 0)
{
value = default(TElement);
priority = default(TPriority);
return false;
}
var element = _elements[0];
_elements[0] = _elements[^1];
_elements.RemoveAt(_elements.Count - 1);
HeapifyDown(0);
value = element.Value!;
priority = element.Priority;
return true;
}
public TElement Peek()
{
if (_elements.Count == 0)
{
throw new InvalidOperationException("The priority queue is empty.");
}
return _elements[0].Value;
}
private void HeapifyUp(int index)
{
while (index > 0)
{
var parentIndex = (index - 1) / 2;
if (_elements[index].Priority.CompareTo(_elements[parentIndex].Priority) >= 0)
{
break;
}
Swap(index, parentIndex);
index = parentIndex;
}
}
private void HeapifyDown(int index)
{
while (index < _elements.Count / 2)
{
var leftChildIndex = 2 * index + 1;
var rightChildIndex = 2 * index + 2;
var smallestChildIndex = leftChildIndex;
if (rightChildIndex < _elements.Count && _elements[rightChildIndex].Priority.CompareTo(_elements[leftChildIndex].Priority) < 0)
{
smallestChildIndex = rightChildIndex;
}
if (_elements[index].Priority.CompareTo(_elements[smallestChildIndex].Priority) <= 0)
{
break;
}
Swap(index, smallestChildIndex);
index = smallestChildIndex;
}
}
private void Swap(int index1, int index2)
{
(_elements[index1], _elements[index2]) = (_elements[index2], _elements[index1]);
}
}
}
#endif