AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
PriorityQueue.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 
4 using System;
5 using System.Collections;
6 using System.Collections.Generic;
7 using System.Linq;
8 
9 namespace HoloToolkit.Unity
10 {
17  class PriorityQueue<TPriority, TValue> : IEnumerable<KeyValuePair<TPriority, TValue>>
18  {
19  public class ValueCollection : IEnumerable<TValue>
20  {
21  private readonly PriorityQueue<TPriority, TValue> parentCollection;
22 
24  {
25  this.parentCollection = parentCollection;
26  }
27 
28  #region IEnumerable
29 
30  public IEnumerator<TValue> GetEnumerator()
31  {
32  foreach (KeyValuePair<TPriority, TValue> pair in parentCollection)
33  {
34  yield return pair.Value;
35  }
36  }
37 
38  IEnumerator IEnumerable.GetEnumerator()
39  {
40  return GetEnumerator();
41  }
42 
43  #endregion
44  }
45 
46  private readonly IComparer<TPriority> priorityComparer;
47 
48  public PriorityQueue() : this(Comparer<TPriority>.Default) { }
49 
50  public PriorityQueue(IComparer<TPriority> comparer)
51  {
52  if (comparer == null)
53  {
54  throw new ArgumentNullException();
55  }
56 
57  priorityComparer = comparer;
58  }
59 
60  private readonly List<KeyValuePair<TPriority, TValue>> queue = new List<KeyValuePair<TPriority, TValue>>();
61  private ValueCollection valueCollection;
62 
63  public ValueCollection Values
64  {
65  get
66  {
67  if (valueCollection == null)
68  {
69  valueCollection = new ValueCollection(this);
70  }
71 
72  return valueCollection;
73  }
74  }
75 
76  #region IEnumerable
77 
78  public IEnumerator<KeyValuePair<TPriority, TValue>> GetEnumerator()
79  {
80  return queue.GetEnumerator();
81  }
82 
83  IEnumerator IEnumerable.GetEnumerator()
84  {
85  return GetEnumerator();
86  }
87 
88  #endregion
89 
93  public void Clear()
94  {
95  queue.Clear();
96  }
97 
103  public void Push(TPriority priority, TValue value)
104  {
105  queue.Add(new KeyValuePair<TPriority, TValue>(priority, value));
106  BubbleUp();
107  }
108 
112  public int Count
113  {
114  get
115  {
116  return queue.Count;
117  }
118  }
119 
123  public KeyValuePair<TPriority, TValue> Top
124  {
125  get
126  {
127  return queue[0];
128  }
129  }
130 
135  public KeyValuePair<TPriority, TValue> Pop()
136  {
137  KeyValuePair<TPriority, TValue> ret = queue[0];
138  queue[0] = queue[queue.Count - 1];
139  queue.RemoveAt(queue.Count - 1);
140  BubbleDown();
141  return ret;
142  }
143 
147  public bool Contains(TValue value)
148  {
149  return queue.Any(itm => EqualityComparer<TValue>.Default.Equals(itm.Value, value));
150  }
151 
155  public bool Remove(TValue value)
156  {
157  int idx = queue.FindIndex(itm => EqualityComparer<TValue>.Default.Equals(itm.Value, value));
158  if (idx == -1)
159  {
160  return false;
161  }
162 
163  queue[idx] = queue[queue.Count - 1];
164  queue.RemoveAt(queue.Count - 1);
165  BubbleDown();
166 
167  return true;
168  }
169 
174  public bool RemoveAtPriority(TPriority priority, Predicate<TValue> shouldRemove)
175  {
176  bool removed = false;
177 
178  for (int i = queue.Count - 1; i >= 0; --i)
179  {
180  // TODO: early out if key < priority
181  if (queue[i].Key.Equals(priority) && (shouldRemove == null || shouldRemove(queue[i].Value)))
182  {
183  queue[i] = queue[queue.Count - 1];
184  queue.RemoveAt(queue.Count - 1);
185  BubbleDown();
186 
187  removed = true;
188  }
189  }
190 
191  return removed;
192  }
193 
197  private void BubbleUp()
198  {
199  int node = queue.Count - 1;
200  while (node > 0)
201  {
202  int parent = (node - 1) >> 1;
203  if (priorityComparer.Compare(queue[parent].Key, queue[node].Key) < 0)
204  {
205  break; // we're in the right order, so we're done
206  }
207  KeyValuePair<TPriority, TValue> tmp = queue[parent];
208  queue[parent] = queue[node];
209  queue[node] = tmp;
210  node = parent;
211  }
212  }
213 
217  private void BubbleDown()
218  {
219  int node = 0;
220  while (true)
221  {
222  // Find smallest child
223  int child0 = (node << 1) + 1;
224  int child1 = (node << 1) + 2;
225  int smallest;
226  if (child0 < queue.Count && child1 < queue.Count)
227  {
228  smallest = priorityComparer.Compare(queue[child0].Key, queue[child1].Key) < 0 ? child0 : child1;
229  }
230  else if (child0 < queue.Count)
231  {
232  smallest = child0;
233  }
234  else if (child1 < queue.Count)
235  {
236  smallest = child1;
237  }
238  else
239  {
240  break; // 'node' is a leaf, since both children are outside the array
241  }
242 
243  if (priorityComparer.Compare(queue[node].Key, queue[smallest].Key) < 0)
244  {
245  break; // we're in the right order, so we're done.
246  }
247 
248  KeyValuePair<TPriority, TValue> tmp = queue[node];
249  queue[node] = queue[smallest];
250  queue[smallest] = tmp;
251  node = smallest;
252  }
253  }
254  }
255 }
PriorityQueue(IComparer< TPriority > comparer)
bool Contains(TValue value)
Returns whether or not the value is contained in the queue
ValueCollection(PriorityQueue< TPriority, TValue > parentCollection)
void Clear()
Clears the priority queue
IEnumerator< KeyValuePair< TPriority, TValue > > GetEnumerator()
bool RemoveAtPriority(TPriority priority, Predicate< TValue > shouldRemove)
Removes all elements with this priority from the queue.
bool Remove(TValue value)
Removes the first element that equals the value from the queue
Min-heap priority queue. In other words, lower priorities will be removed from the queue first...
void Push(TPriority priority, TValue value)
Add an element to the priority queue.
KeyValuePair< TPriority, TValue > Pop()
Pop the minimal element of the queue. Will fail at runtime if queue is empty.