Skip to content

Commit 948f9cb

Browse files
committed
Fixed some stuff and added some tests
1 parent b4d55ae commit 948f9cb

10 files changed

+736
-1
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,4 +360,5 @@ MigrationBackup/
360360
.ionide/
361361

362362
# Fody - auto-generated XML schema
363-
FodyWeavers.xsd
363+
FodyWeavers.xsd
364+
/PriorityQueues/LICENSE.txt

PriorityQueue.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.31321.278
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PriorityQueues", "PriorityQueues\PriorityQueues.csproj", "{68BC24ED-9C80-4BE1-8FBC-21E42AF7E1BD}"
77
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{E52EC0BD-072A-42DC-83B8-FA45A8801B5A}"
9+
EndProject
810
Global
911
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1012
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
1517
{68BC24ED-9C80-4BE1-8FBC-21E42AF7E1BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
1618
{68BC24ED-9C80-4BE1-8FBC-21E42AF7E1BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
1719
{68BC24ED-9C80-4BE1-8FBC-21E42AF7E1BD}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{E52EC0BD-072A-42DC-83B8-FA45A8801B5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{E52EC0BD-072A-42DC-83B8-FA45A8801B5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{E52EC0BD-072A-42DC-83B8-FA45A8801B5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{E52EC0BD-072A-42DC-83B8-FA45A8801B5A}.Release|Any CPU.Build.0 = Release|Any CPU
1824
EndGlobalSection
1925
GlobalSection(SolutionProperties) = preSolution
2026
HideSolutionNode = FALSE
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace PriorityQueues
7+
{
8+
/// <summary>
9+
/// Priority queue implementation based on a binary heap
10+
/// </summary>
11+
public class BinaryPriorityQueue<T> : IPriorityQueue<T>
12+
{
13+
#region Private fields
14+
protected List<T> _heap;
15+
protected readonly Comparison<T> _comparer;
16+
#endregion
17+
18+
#region Public properties
19+
/// <inheritdoc/>
20+
public int Count => _heap.Count;
21+
#endregion
22+
23+
#region Constructors
24+
/// <summary>
25+
/// Initializes a new instance of the <see cref="BinaryPriorityQueue{T}"/> class that is empty and has the default initial capacity
26+
/// </summary>
27+
/// <param name="comparer"></param>
28+
public BinaryPriorityQueue(Comparison<T> comparer)
29+
{
30+
_heap = new List<T>();
31+
_comparer = comparer;
32+
}
33+
34+
/// <summary>
35+
/// Initializes a new instance of the <see cref="BinaryPriorityQueue{T}"/> class that is empty and has the specified initial capacity
36+
/// </summary>
37+
/// <param name="capacity">The number of elements the <see cref="BinaryPriorityQueue{T}"/> can initially store</param>
38+
/// <param name="comparer"></param>
39+
public BinaryPriorityQueue(int capacity, Comparison<T> comparer)
40+
{
41+
_heap = new List<T>(capacity);
42+
_comparer = comparer;
43+
}
44+
45+
/// <summary>
46+
/// Initializes a new instance of the <see cref="BinaryPriorityQueue{T}"/> class that contains elements copied from the specified collection, sorted by their priority value
47+
/// </summary>
48+
/// <param name="collection">The collection whose elements are copied to the <see cref="BinaryPriorityQueue{T}"/></param>
49+
/// <param name="comparer"></param>
50+
public BinaryPriorityQueue(IEnumerable<T> collection, Comparison<T> comparer)
51+
{
52+
_heap = new List<T>(collection.Count());
53+
_comparer = comparer;
54+
55+
int i = 0;
56+
foreach (var elem in collection)
57+
{
58+
_heap.Add(elem);
59+
}
60+
61+
// heapify process
62+
for (int j = Math.Max(0, (_heap.Count / 2) - 1); j >= 0; j--)
63+
{
64+
Sink(i);
65+
}
66+
}
67+
#endregion
68+
69+
#region Public methods
70+
/// <inheritdoc/>
71+
public virtual void Clear()
72+
{
73+
_heap.Clear();
74+
}
75+
76+
/// <inheritdoc/>
77+
public virtual bool Contains(T element)
78+
{
79+
if (element == null)
80+
{
81+
throw new ArgumentNullException("element");
82+
}
83+
84+
// do a linear scan
85+
foreach (var elem in _heap)
86+
{
87+
if (elem.Equals(element))
88+
{
89+
return true;
90+
}
91+
}
92+
return false;
93+
}
94+
95+
/// <inheritdoc/>
96+
public virtual T Dequeue()
97+
{
98+
return IsEmpty() ? throw new InvalidOperationException("Queue is empty") : RemoveAt(0);
99+
}
100+
101+
/// <inheritdoc/>
102+
public virtual void Enqueue(T element)
103+
{
104+
if (element == null)
105+
{
106+
throw new ArgumentNullException("element");
107+
}
108+
109+
_heap.Add(element);
110+
111+
Swim(_heap.Count - 1);
112+
}
113+
114+
/// <inheritdoc/>
115+
public virtual bool IsEmpty()
116+
{
117+
return Count == 0;
118+
}
119+
120+
/// <inheritdoc/>
121+
public virtual T Peek()
122+
{
123+
return IsEmpty() ? throw new InvalidOperationException("Queue is empty") : _heap[0];
124+
}
125+
126+
/// <inheritdoc/>
127+
public virtual bool Remove(T element)
128+
{
129+
if (element == null)
130+
{
131+
return false;
132+
}
133+
134+
for (int i = 0; i < Count; i++)
135+
{
136+
if (_heap[i].Equals(element))
137+
{
138+
RemoveAt(i);
139+
return true;
140+
}
141+
}
142+
return false;
143+
}
144+
#endregion
145+
146+
#region Private methods
147+
protected bool IsHeapInvariantMaintained(int index)
148+
{
149+
if (index >= Count)
150+
{
151+
return true;
152+
}
153+
154+
int leftIndex = 2 * index + 1;
155+
int rightIndex = 2 * index + 2;
156+
157+
if (leftIndex < Count && !Less(index, leftIndex)) {
158+
return false;
159+
}
160+
if (rightIndex < Count && !Less(index, rightIndex)) {
161+
return false;
162+
}
163+
164+
return IsHeapInvariantMaintained(leftIndex) && IsHeapInvariantMaintained(rightIndex);
165+
}
166+
167+
protected bool Less(int i, int j)
168+
{
169+
return _comparer(_heap[i], _heap[j]) <= 0;
170+
}
171+
172+
protected void Swim(int index)
173+
{
174+
int parentIndex = (index - 1) / 2;
175+
176+
while (index > 0 && Less(index, parentIndex))
177+
{
178+
Swap(parentIndex, index);
179+
index = parentIndex;
180+
parentIndex = (index - 1) / 2;
181+
}
182+
}
183+
184+
protected void Sink(int index)
185+
{
186+
while (true)
187+
{
188+
int leftChildIndex = 2 * index + 1;
189+
int rightChildIndex = 2 * index + 2;
190+
int smallerNodeIndex = leftChildIndex;
191+
if (rightChildIndex < Count && Less(rightChildIndex, leftChildIndex))
192+
{
193+
smallerNodeIndex = rightChildIndex;
194+
}
195+
196+
// stop if we're outside bounds or we cannot sink anymore
197+
if (leftChildIndex >= Count || Less(index, smallerNodeIndex))
198+
{
199+
break;
200+
}
201+
202+
Swap(smallerNodeIndex, index);
203+
index = smallerNodeIndex;
204+
}
205+
}
206+
207+
protected virtual void Swap(int i, int j)
208+
{
209+
T i_elem = _heap[i];
210+
T j_elem = _heap[j];
211+
212+
_heap[i] = j_elem;
213+
_heap[j] = i_elem;
214+
}
215+
216+
protected virtual T RemoveAt(int index)
217+
{
218+
if (index < 0 || index > Count - 1)
219+
{
220+
throw new ArgumentOutOfRangeException("index", index, string.Empty);
221+
}
222+
223+
T removedElem = _heap[index];
224+
225+
Swap(index, Count - 1);
226+
227+
_heap.RemoveAt(Count - 1);
228+
229+
if (IsEmpty()) {
230+
return removedElem;
231+
}
232+
233+
T elem = _heap[index];
234+
Sink(index);
235+
if (_heap[index].Equals(elem))
236+
{
237+
Swim(index);
238+
}
239+
240+
return removedElem;
241+
}
242+
#endregion
243+
244+
#region IEnumerable interface implementation
245+
public IEnumerator<T> GetEnumerator()
246+
{
247+
return ((IEnumerable<T>)_heap).GetEnumerator();
248+
}
249+
250+
IEnumerator IEnumerable.GetEnumerator()
251+
{
252+
return ((IEnumerable)_heap).GetEnumerator();
253+
}
254+
#endregion
255+
}
256+
}

PriorityQueues/IPriorityQueue.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
namespace PriorityQueues
55
{
6+
/// <summary>
7+
/// Represents a generic priority queue
8+
/// </summary>
69
public interface IPriorityQueue<T> : IEnumerable<T>
710
{
811
/// <summary>

0 commit comments

Comments
 (0)